home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / MAILBOX2.C < prev    next >
C/C++ Source or Header  |  1997-08-18  |  67KB  |  2,713 lines

  1. /* NOTE: because of size, the previous 'mailbox.c' has been
  2.  * split in 3 parts:
  3.  * pbbscmd.c, containing the 'pbbs' subcommands, and
  4.  * mailbox.c, containing some user mailbox commands, and
  5.  * mailbox2.c, containing the remaining user commands.
  6.  * 921125 - WG7J
  7.  */
  8. /* There are only two functions in this mailbox code that depend on the
  9.  * underlying protocol, namely mbx_getname() and dochat(). All the other
  10.  * functions can hopefully be used without modification on other stream
  11.  * oriented protocols than AX.25 or NET/ROM.
  12.  *
  13.  * SM0RGV 890506, most work done previously by W9NK
  14.  *
  15.  *** Changed 900114 by KA9Q to use newline mapping features in stream socket
  16.  *    interface code; everything here uses C eol convention (\n)
  17.  *
  18.  *    Numerous new commands and other changes by SM0RGV, 900120
  19.  *
  20.  * Gateway function now support outgoing connects with the user's call
  21.  * with inverted ssid. Users can connect to system alias as well...
  22.  * See also several mods in socket.c,ax25.c and others
  23.  * 11/15/91, WG7J/PA3DIS
  24.  *
  25.  * Userlogging, RM,VM and KM commands, and R:-line interpretation
  26.  * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
  27.  *
  28.  * Inactivity timeout-disconnect added 920325 and later - WG7J
  29.  *
  30.  * Removed pbbs overhead from calling Convers directly from ax25 - KO4KS
  31.  * Several other additions - KO4KS
  32.  */
  33. #include "global.h"
  34. #include "ctype.h"
  35. #include "commands.h"
  36. #ifdef MSDOS
  37. #include <dir.h>
  38. #include <dos.h>
  39. #else
  40. #include <time.h>
  41. #endif
  42. #ifdef  UNIX
  43. #include <sys/stat.h>
  44. #endif
  45. #include "timer.h"
  46. #include "proc.h"
  47. #include "socket.h"
  48. #include "usock.h"
  49. #include "session.h"
  50. #include "smtp.h"
  51. #include "ftpserv.h"
  52. #include "bm.h"
  53. #include "pktdrvr.h"
  54. #include "help.h"
  55.  
  56. #if !defined(_lint)
  57. static char rcsid[] OPTIONAL = "$Id: mailbox2.c,v 1.32 1997/08/19 01:19:22 root Exp root $";
  58. #endif
  59.  
  60. #ifdef DELEGATE
  61. #include "delegate.h"
  62. extern int Mbdelegate;
  63. #endif
  64.  
  65. #ifdef UNIX
  66. extern int ftpsecuritycheck (char *filename, int perms, int mode);
  67. extern long CREATEgid, CREATEuid;
  68. extern short CREATEmask;
  69. extern int CREATEsecure;
  70.  
  71. #ifndef R_OK
  72. #define R_OK 4
  73. #endif
  74. #ifndef W_OK
  75. #define W_OK 2
  76. #endif
  77. #endif
  78.  
  79. extern int AMPRonly;
  80. extern char Compiled[];
  81. extern int MAttended;
  82. extern char *MAttendedAt;
  83. extern char Mbpasswd[];
  84. extern int BbsUsers;
  85. extern char Only[];
  86. extern char CurUsers[];
  87. extern char Howtoend[];
  88. extern char MsgAborted[];
  89. extern char *findhome (char *);
  90. extern void suspendTipMail (struct mbx *m);
  91. extern void tutorserv (const char *call, struct mbx *m, int mode, int color, int ip);
  92.  
  93. #ifdef MBFWD
  94. extern void forwardingSummary (void);
  95. #endif
  96.  
  97. extern int dombusers (int argc, char *argv[], void *p);
  98. extern struct list *expandalias (struct list **head, const char *user, const char *orig);
  99. extern char *Mbhaddress;
  100. extern int doencode (int argc, char *argv[], void *p);
  101. extern struct cmds Cmds[];
  102. extern struct cmds Mbcmds[];
  103.  
  104.  
  105. #ifdef MAILBOX
  106. void bbsbump (char *user, int zap);
  107. int bid_check (register char *string);
  108. #ifdef WPAGES
  109. static void wpageUpdate (FILE * fp, char *string, char *entry, char *oldtime, int bbs, int updateit, char which);
  110. #endif
  111. int groupcommand (char *action, char *group, char *user, int local, FILE ** out, FILE * in);
  112. int isgroup (char *group);
  113. static void informGroup (char *action, char *group, char *user, char *buf, FILE * old, FILE * new, FILE * in);
  114.  
  115. #ifdef USERLOG
  116. static int quickstat (register struct mbx *m, char *area);
  117. #endif
  118.  
  119. static int dombgetall (struct mbx *m);
  120. static void expertstat (struct mbx *m);
  121.  
  122. #ifdef FILECMDS
  123. static int uuencode (FILE *infile, int s, char *infilename);
  124. static int uudecode (FILE *infile, FILE *outfile);
  125. #endif
  126.  
  127. int dombencode (int argc, char *argv[], void *p);
  128. int dodownload (int argc, char *argv[], void *p);
  129. int dombfdesc (int argc, char *argv[], void *p);
  130. int dobump (int argc, char *argv[], void *p);
  131. int msgidcheck (char *string);
  132. int dombwpages (int argc, char *argv[], void *p);
  133. int dombnews (int argc, char *argv[], void *p);
  134. int dombtutor (int argc, char *argv[], void *p);
  135. int dombgroup (int argc, char *argv[], void *p);
  136. int dombquote (int argc, char *argv[], void *p);
  137. int dombset (int argc, char *argv[], void *p);
  138. int dombrmail (int argc, char *argv[], void *p);
  139. int dombroute (int argc, char *argv[], void *p);
  140. int dombexpand (int argc, char *argv[], void *p);
  141. int dombexpert (int argc, char *argv[], void *p);
  142. int dombslip (int argc, char *argv[], void *p);
  143. int douser (int argc, char *argv[], void *p);
  144. int doreply (int argc, char *argv[], void *p);
  145. int dombget (int argc, char *argv[], void *p);
  146. int dombmovemail (int argc, char *argv[], void *p);
  147. int dombhelp (int argc, char *argv[], void *p);
  148. int dombconvers (int argc, char *argv[], void *p);
  149. int dombfinger (int argc, char *argv[], void *p);
  150. int dosysop (int argc, char *argv[], void *p);
  151. int dostars (int argc, char *argv[], void *p);
  152. int dochat (int argc, char *argv[], void *p);
  153. int dombjheard (int argc, char *argv[], void *p);
  154. int dombiproute (int argc, char *argv[], void *p);
  155.  
  156. #ifdef LZW
  157. void togglelzw (int soc, int mode);
  158. #endif
  159.  
  160. #ifdef WPAGES
  161. void wpageAdd (char *entry, int bbs, int updateit, char which);
  162. char *wpageCheck (char *string, int bbs, int updateit, char which);
  163. void add_WPUpdate (char *call, char *home, char *name, char which);
  164. #endif
  165.  
  166. char *wpage_exp (char *to, int hier, int exphome);
  167. int dozap (int argc, char *argv[], void *p);
  168. int dowhat (int argc, char *argv[], void *p);
  169. extern int dosend (int argc, char *argv[], void *p);
  170. extern char *permtest (char *path, long privs, const char *name, int mode, char *root, int thedir);
  171. extern char *cmd_line (int argc, char *argv[], char stype);
  172. extern char *nntp_name_expansion (char *name);
  173. extern void updateCtl (const char *who, struct let *info);
  174.  
  175. #if defined(FOQ_CMDS) || defined(TTYCALL) || defined(ALLSERV)
  176. const char SysopBusy[] = "The system is unattended. Try again later.\n";
  177. #endif
  178.  
  179. #ifdef CATALOG
  180. #include "catalog.h"
  181.  
  182. #define CAT mailbox2_catalog
  183.  
  184. #define Alsomenu        __STR(0)
  185. #define Alsomenu2        __STR(1)
  186. #define index_dat        __STR(2)
  187. #define sorry            __STR(3)
  188. #define wr_syntax        __STR(4)
  189. #define wa_syntax        __STR(5)
  190. #define noread            __STR(6)
  191. #define dirdenied        __STR(7)
  192. #define zapfailed        __STR(8)
  193. #define logzap            __STR(9)
  194. #define zapdenied        __STR(10)
  195. #define attemptsysop        __STR(11)
  196. #define sysopdenied        __STR(12)
  197. #define validationcomplete    __STR(13)
  198. #define sysopwarning        __STR(14)
  199. #define logsysop        __STR(15)
  200. #define loglinkdenied        __STR(16)
  201. #define loglink            __STR(17)
  202. #define linkhello        __STR(18)
  203. #define ampronly_str        __STR(19)
  204. #define telnetdenied        __STR(20)
  205. #define logtelnet        __STR(21)
  206. #define incomingcall        __STR(22)
  207. #define finger_usage        __STR(23)
  208. #define confnotenabled        __STR(24)
  209. #define convdenied        __STR(25)
  210. #define logconf            __STR(26)
  211. #define logtutor        __STR(27)
  212. #define nohelp            __STR(28)
  213. #define onlyfirst        __STR(29)
  214. #define cannotlock        __STR(30)
  215. #define message            __STR(31)
  216. #define moreafter        __STR(32)
  217. #define areaadded        __STR(33)
  218. #define nameadded        __STR(34)
  219. #define newscanlogin        __STR(35)
  220. #define usaANSI            __STR(36)
  221. #define permissionlevel        __STR(37)
  222. #define fwddelegation        __STR(38)
  223. #define usecompressed        __STR(39)
  224. #define expertprompts        __STR(40)
  225. #define usersettings        __STR(41)
  226. #define useSET            __STR(42)
  227. #define getheader        __STR(43)
  228. #define gettrailer        __STR(44)
  229. #define noconfig        __STR(45)
  230. #define delegationdisabled    __STR(46)
  231. #define expandsto        __STR(47)
  232. #define noaddress        __STR(48)
  233. #define addressroutes        __STR(49)
  234. #define unreadmessages        __STR(50)
  235. #define newmessages        __STR(51)
  236. #define nounreadmessages    __STR(52)
  237. #if 0
  238. #define systemtime        __STR(53)
  239. #endif
  240. #define inform_str        __STR(54)
  241. #define groupindex        __STR(55)
  242. #define newsdisabled        __STR(56)
  243. #define lognews            __STR(57)
  244. #define wp_syntax        __STR(58)
  245. #define notinwp            __STR(59)
  246. #if 0
  247. #define wplists            __STR(60)
  248. #endif
  249. #define wplists2        __STR(61)
  250. #define wp_sysopsyntax        __STR(62)
  251. #define updating        __STR(63)
  252. #define filedesc        __STR(64)
  253. #define downloaddenied        __STR(65)
  254. #define xmodemtip        __STR(66)
  255. #define uploaddenied        __STR(67)
  256. #define cannotopen        __STR(68)
  257. #define cannotcreate        __STR(69)
  258. #define logupload        __STR(70)
  259. #define Sysopmenu        __STR(71)
  260.  
  261. #else
  262. static const char Alsomenu[] =
  263. "\nFor further help, type 'help cmdname', where 'cmdname' is one of the above."
  264. "\nFor a brief listing of all commands, type '?'\n\n";
  265. static const char Alsomenu2[] =
  266. "Others: AF, AL, AN, AS, DU, KM, KS, KU, L$, L>, L<, LA, LB, LL, LM, LS, LT,\n"
  267. "        ML, MS, RH, RM, SB, SC, SF, SP, SR, ST, VM, XA, XC, XM, XN, XS\n";
  268. static const char Sysopmenu[] = "Sysops: IF, MA, MC, MF, MH, MK, MM, MP, MR, MT, MW, MX, WA, WR, @\n";
  269. static const char index_dat[] = "index.dat";
  270. static const char sorry[] = "Sorry, command is only available to the SYSOP!\n";
  271. static const char wr_syntax[] = "Syntax: WR user \"message\"\n";
  272. static const char wa_syntax[] = "Syntax: WA \"message\"\n";
  273. static const char noread[] = "Can't read directory: \"%s\": %s\n";
  274. static const char dirdenied[] = "%s: directory denied: %s\n";
  275. static const char zapfailed[] = "Zap failed: %s\n";
  276. static const char logzap[] = "PBBS Zap: %s";
  277. static const char zapdenied[] = "%s: zap denied: %s\n";
  278. static const char attemptsysop[] = "PBBS: %s attempting SYSOP";
  279. static const char sysopdenied[] = "%s: SYSOP denied!\n";
  280. static const char validationcomplete[] = "Validation %somplete!\n";
  281. static const char sysopwarning[] = "\nType 'exit' to return\n\nBe VERY careful!!\n";
  282. static const char logsysop[] = "PBBS sysop: %s";
  283. static const char loglinkdenied[] = "PBBS LINKED: %s permission denied";
  284. static const char loglink[] = "PBBS LINKED: %s changed to %s";
  285. static const char linkhello[] = "Oh, hello %s.\n";
  286. static const char ampronly_str[] = "Sorry, but only Amateur Radio IP stations can be reached from here!\n";
  287. static const char telnetdenied[] = "%s: Telnet denied: %s\n";
  288. static const char logtelnet[] = "PBBS TELNET: %s to %s:%d";
  289. static const char incomingcall[] = "*** Incoming call from %s@%s ***\n";
  290. static const char finger_usage[] = "Usage: F user@host  or  F @host  or  F user.\n";
  291. static const char confnotenabled[] = "Conference server not enabled\n";
  292. static const char convdenied[] = "%s: converse denied\n";
  293. static const char logconf[] = "PBBS CONFERENCE: %s";
  294. static const char logtutor[] = "PBBS TUTORIAL: %s";
  295. static const char nohelp[] = "No help available.\n";
  296. static const char onlyfirst[] = "Only first %d arguments used\n";
  297. static const char cannotlock[] = "Can't lock '%s', please try later\n";
  298. static const char message[] = "Message %d %s...\n";
  299. static const char moreafter[] = "-more- after %d lines\n";
  300. static const char areaadded[] = "Area added to prompt";
  301. static const char nameadded[] = "Name added to prompt";
  302. static const char newscanlogin[] = "New message scan at login";
  303. static const char usaANSI[] = "Use ANSI color graphics";
  304. static const char permissionlevel[] = "Permission level: %ld (0x%08lx)\n";
  305. static const char fwddelegation[] = "Forward delegation";
  306. static const char usecompressed[] = "Use Compressed streams";
  307. static const char expertprompts[] = "Expert user prompts";
  308. static const char usersettings[] = "*** User profile settings: %s ***\n\n";
  309. static const char useSET[] = "\nUse the SET command to change these options. For help, type HELP SET.\n";
  310. static const char getheader[] = "---------------- Current %s Information ----------------\n";
  311. static const char gettrailer[] = "---------------- %s %s Information ----------------\n";
  312. static const char noconfig[] = "This command not configured for this interface\n";
  313. static const char delegationdisabled[] = "Forwarding delegation disabled by SYSOP\n";
  314. static const char expandsto[] = "Address '%s' expands to: ";
  315. static const char noaddress[] = "No address specified.\n";
  316. static const char addressroutes[] = "Address '%s' routes to:";
  317. static const char unreadmessages[] = "%s ha%s unread messages, in the following message areas:\n";
  318. static const char newmessages[] = "As a new user, you will find messages in the following message areas:\n";
  319. static const char nounreadmessages[] = "No unread messages in the public areas! %s %s up-to-date!\n";
  320.  
  321. #if 0
  322. static const char systemtime[] = "The system time at '%s' is now: %s\n";
  323. #endif
  324.  
  325. static const char inform_str[] = "%s: SUBSCRIBED %s";
  326. static const char groupindex[] = "Index of mailing lists/groups\n\n";
  327. static const char newsdisabled[] = "News Center not enabled\n";
  328. static const char lognews[] = "PBBS NEWS: %s";
  329. static const char wp_syntax[] = "Syntax: WP user%s\n";
  330. static const char notinwp[] = "Sorry, user not in whitepages! If local user, try \"ML user\"...\n";
  331.  
  332. #if 0
  333. static const char wplists[] = "White Pages lists this person as '%s@%s'\n";
  334. #endif
  335.  
  336. static const char wplists2[] = "White Pages lists this person as '%s'\n";
  337. static const char wp_sysopsyntax[] = "Syntax: WP user @bbsname\n";
  338. static const char updating[] = "Updating database....\n";
  339. static const char filedesc[] = "Enter description lines, each line 37 characters maximum.\n'/EX' when complete:\n";
  340. static const char downloaddenied[] = "%s: download denied: %s\n";
  341. static const char xmodemtip[] = "Xmodem on TIP connects only\n";
  342. static const char uploaddenied[] = "%s: upload denied: %s\n";
  343. static const char cannotopen[] = "Can't open \"%s\": %s\n";
  344. static const char cannotcreate[] = "Can't create \"%s\": %s\n";
  345. static const char logupload[] = "PBBS upload: %s";
  346.  
  347. #endif
  348.  
  349.  
  350. short SecureTelnet = 1;
  351.  
  352.  
  353. #ifdef MSDOS
  354. #define WPAGEENTRYSIZE    30
  355. #define WPAGEBBSENTRYSIZE 49
  356. #else
  357. #define WPAGEENTRYSIZE    29
  358. #define WPAGEBBSENTRYSIZE 48
  359. #endif
  360.  
  361.  
  362.  
  363. int
  364. dowhat (int argc, char *argv[], void *p)
  365. {
  366. struct mbx *m;
  367. #ifdef FILECMDS
  368. FILE *fp, *in = NULLFILE;
  369. char *file;
  370. char *cp, *nm, *ptr;
  371. char buf[50], buf2[80];
  372. int yep;
  373. #endif
  374. #ifdef DOS_GETFILEATTR
  375. unsigned attr;
  376. #endif
  377.  
  378.     m = (struct mbx *) p;
  379. #ifdef WPAGES
  380.     if (m->stype == 'P')
  381.         return (dombwpages (argc, argv, p));
  382. #endif
  383.     if (((m->stype == 'R') || (m->stype == 'A')) && !(m->privs & SYSOP_CMD)) {
  384.         tputs (sorry);
  385.         return 0;
  386.     }
  387.     if (m->stype == 'R') {
  388.         if (argc < 3)
  389.             tputs (wr_syntax);
  390.         else
  391.             (void) dowrite (0, argv, 0);
  392.         return 0;
  393.     }
  394.     if (m->stype == 'A') {
  395.         if (argc < 2)
  396.             tputs (wa_syntax);
  397.         else
  398.             (void) dowriteall (0, argv, 0);
  399.         return 0;
  400.     }
  401. #ifdef FILECMDS
  402.     if ((file = permtest (m->path, m->privs, (argc > 1) ? argv[1] : ".", RETR_CMD, NULLCHAR, (argc < 2))) != NULLCHAR) {
  403.         m->state = MBX_WHAT;
  404.  
  405.         /* check for index.dat file in that directory */
  406.         cp = strdup (file);
  407. #ifdef DOS_GETFILEATTR
  408.         (void) _dos_getfileattr (cp, &attr);
  409.         if (!(attr & FA_DIREC)) {
  410.             ptr = strrchr (cp, '/');
  411.             if (ptr)
  412.                 *ptr = 0;
  413.         }
  414. #endif
  415.         nm = pathname (cp, index_dat);
  416.         free (cp);
  417.         in = fopen (nm, READ_TEXT);
  418.         free (nm);
  419.         if (in != NULLFILE) {
  420.             tputc ('\n');
  421.             while (fgets (buf2, 80, in) != NULLCHAR) {
  422.                 if (*buf2 == ' ' || *buf2 == '\t' || *buf2 == '\n')
  423.                     tputs (buf2);
  424.                 else
  425.                     break;
  426.             }
  427.         }
  428.         if ((fp = dir (file, (in == NULLFILE) ? 1 : 2)) == NULLFILE)
  429.             tprintf (noread, file, SYS_ERRLIST(errno));
  430.         else {
  431. #ifdef MBXTDISC
  432.             stop_timer (&m->tdisc);
  433. #endif
  434.             if (in == NULLFILE)
  435.                 (void) sendfile (fp, m->user, ASCII_TYPE, 0);
  436.             else {
  437.                 while (fgets (buf, 50, fp) != NULLCHAR) {
  438.                     yep = 0;
  439.                     if (*buf == ' ')
  440.                         continue;
  441.                     rewind (in);
  442.                     while (fgets (buf2, 80, in) != NULLCHAR) {
  443.                         if (!strnicmp (buf, buf2, 12)) {
  444.                             yep = 1;
  445.                             rip (buf2);
  446.                             break;
  447.                         }
  448.                     }
  449.                     if (yep)
  450.                         rip (buf);
  451.                     tputs (buf);
  452.                     if (yep) {
  453.                         ptr = &buf2[13];
  454.                         ptr = skipwhite (ptr);
  455.                         tprintf ("%-37.37s\n", ptr);
  456.                         while (fgets (buf2, 80, in) != NULLCHAR) {
  457.                             if (*buf2 != ' ' && *buf2 != '\t')
  458.                                 break;
  459.                             rip (buf2);
  460.                             ptr = skipwhite (buf2);
  461.                             tprintf ("%39s| %-37.37s\n", "", ptr);
  462.                         }
  463.                     }
  464.                 }
  465.                 (void) fclose (in);
  466.             }
  467.             (void) fclose (fp);
  468.         }
  469.         free (file);
  470.     } else {
  471.         tputs (Noperm);
  472.         mail_error (dirdenied, m->name, cmd_line (argc, argv, m->stype));
  473.     }
  474. #endif
  475.     return 0;
  476. }
  477.  
  478.  
  479.  
  480. #ifdef FILECMDS
  481. int
  482. dozap (int argc, char *argv[], void *p)
  483. {
  484. struct mbx *m;
  485. char *file;
  486.  
  487.     m = (struct mbx *) p;
  488.     if ((file = permtest (m->path, m->privs, argv[1], DELE_CMD, NULLCHAR, 0)) != NULLCHAR) {
  489.         if (unlink (file))
  490.             tprintf (zapfailed, SYS_ERRLIST(errno));
  491.         else
  492.             log (m->user, logzap, file);
  493.         free (file);
  494.     } else {
  495.         tputs (Noperm);
  496.         mail_error (zapdenied, m->name, cmd_line (argc, argv, m->stype));
  497.     }
  498.     return 0;
  499. }
  500. #endif
  501.  
  502.  
  503.  
  504. extern void dumproute (struct route *rp, char *p);
  505. extern const char RouteHeader[];
  506.  
  507.  
  508.  
  509. /* Show non-private routes only */
  510. int
  511. dombiproute (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  512. {
  513. register int i, bits;
  514. register struct route *rp;
  515. char buf[85];
  516.  
  517.     tputs (RouteHeader);
  518.     for (bits = 31; bits >= 0; bits--) {
  519.         for (i = 0; i < HASHMOD; i++) {
  520.             for (rp = Routes[bits][i]; rp != NULLROUTE; rp = rp->next) {
  521.                 if (!(rp->flags & RTPRIVATE)) {
  522.                     dumproute (rp, buf);
  523.                     if (tprintf ("%s\n", &buf[4]) == EOF)
  524.                         return 0;
  525.                 }
  526.             }
  527.         }
  528.     }
  529.     if (R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
  530.         dumproute (&R_default, buf);
  531.         if (tprintf ("%s\n", &buf[4]) == EOF)
  532.             return 0;
  533.     }
  534.     return 0;
  535. }
  536.  
  537.  
  538.  
  539. #ifdef AX25
  540. int
  541. dombjheard (int argc, char *argv[], void *p)
  542. {
  543. struct iface *ifp;
  544. struct mbx *m = (struct mbx *) p;
  545.  
  546.     if (argc > 1) {
  547.         if (((ifp = if_lookup (argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
  548.             ((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP))) {
  549.             tprintf (Badinterface, argv[1]);
  550.             return 0;
  551.         }
  552.         (void) axheard (ifp);
  553.         return 0;
  554.     }
  555.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
  556.         if ((ifp->flags & LOG_AXHEARD) && (!(ifp->flags & HIDE_PORT) || m->privs & MBX_SYSOP))
  557.             if (axheard (ifp) == EOF)
  558.                 break;
  559.     }
  560.     return 0;
  561. }
  562. #endif
  563.  
  564.  
  565.  
  566. #if defined(FOQ_CMDS) || defined(TTYCALL)
  567. int
  568. dochat (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  569. {
  570. char buf[8], *newargv[3], doitat[50], buf2[2];
  571. struct mbx *m;
  572.  
  573.     m = (struct mbx *) p;
  574.  
  575.     if (MAttended) {
  576.         m->state = MBX_CHAT;
  577.         strcpy (buf2, "C");
  578.         newargv[0] = buf2;
  579.         newargv[1] = Hostname;
  580.         if (MAttendedAt != NULLCHAR) {
  581.             strncpy (doitat, MAttendedAt, 50);
  582.             newargv[1] = doitat;
  583.             rip (newargv[1]);
  584.         }
  585.         sprintf (buf, "%d", IPPORT_TTYLINK);
  586.         newargv[2] = buf;
  587.         SecureTelnet = 0;
  588.         m->stype = '+';
  589.         (void) dombtelnet (3, newargv, p);
  590.     } else
  591.         tputs (SysopBusy);
  592.  
  593.     /* It returns only after a disconnect or refusal */
  594.     return 0;
  595. }
  596. #endif
  597.  
  598.  
  599.  
  600. /*Password protection added - 920118, WG7J */
  601. int
  602. dosysop (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  603. {
  604. struct mbx *m;
  605. int c;
  606. int len, pwdc[5], i, valid = 0;
  607. char *cp;
  608.  
  609.     m = (struct mbx *) p;
  610.     log (m->user, attemptsysop, m->name);
  611.  
  612.     /*If you want anyone with the password to go sysop-mode
  613.      *comment out the next 4 line ! -WG7J
  614.      */
  615.     if (!(m->privs & SYSOP_CMD)) {
  616.         tputs (Noperm);
  617.         mail_error (sysopdenied, m->name);
  618.         return 0;
  619.     }
  620.     /*only if set,
  621.      *check for the password before letting users proceed
  622.      */
  623.     m->state = MBX_SYSOPTRY;
  624.     if ((len = (int) strlen (Mbpasswd)) != 0) {
  625.         for (i = 0; i < 5; i++)
  626.             tprintf ("%d ", (pwdc[i] = RANDOM (len)) + 1);    /*print the random chars*/
  627.         tputc ('\n');
  628.         for ( ; ; ) {
  629.             c = mbxrecvline (m);
  630.             if (c == EOF || c == -2)
  631.                 return 0;
  632.             if (*m->line == '\0')
  633.                 break;
  634.             if (*m->line == '?') {
  635.                 tprintf (validationcomplete, valid ? "C" : "Inc");
  636.                 continue;
  637.             }
  638.             cp = m->line;
  639.             for (i = 0; i < 5; i++)
  640.                 if (tolower (*cp++) != tolower (Mbpasswd[pwdc[i]]))
  641.                     break;
  642.             if (i == 5)
  643.                 valid = 1;
  644.         }
  645.         if (!valid)
  646.             return 0;
  647.     }
  648.     log (m->user, "PBBS: %s is now SYSOP", m->name);
  649.     m->state = MBX_SYSOP;
  650.     tputs (sysopwarning);
  651.  
  652.     for ( ; ; ) {
  653.         netPrompt ();
  654.         usflush (Curproc->output);
  655.         if (mbxrecvline (m) < 0)
  656.             break;
  657.         log (m->user, logsysop, m->line);
  658. #ifdef MBXTDISC
  659.         stop_timer (&m->tdisc);
  660. #endif
  661.         if (*m->line == '\0')
  662.             continue;
  663.  
  664.         cp = _variable_expansion (strdup (m->line));
  665.         strncpy (m->line, cp, MBXLINE);
  666.         free (cp);
  667.         /* Check for special commands. Execute these mailbox cmds. KF5MG. */
  668. #if defined AX25 || defined NETROM
  669.         if (strncmp (m->line, "connect", strcspn (m->line, " ")) == 0)
  670.             valid = cmdparse (Mbcmds, m->line, (void *) m);
  671.         else
  672. #endif
  673. #ifdef FOQ_CMDS
  674.         if (strncmp (m->line, "finger", strcspn (m->line, " ")) == 0)
  675.             valid = cmdparse (Mbcmds, m->line, (void *) m);
  676.         else
  677. #endif
  678. #ifdef GATECMDS
  679.         if (strncmp (m->line, "ping", strcspn (m->line, " ")) == 0)
  680.             valid = cmdparse (Mbcmds, m->line, (void *) m);
  681.         else if (strncmp (m->line, "telnet", strcspn (m->line, " ")) == 0)
  682.             valid = cmdparse (Mbcmds, m->line, (void *) m);
  683.         else
  684. #endif
  685.  
  686.             valid = cmdparse (Cmds, m->line, NULL);
  687. #ifdef MBXTDISC
  688.         start_timer (&m->tdisc);
  689. #endif
  690.         if (valid == -2)
  691.             break;
  692.     }
  693.     /* remove potential remote traces - WG7J */
  694.     removetrace ();
  695.     return 0;
  696. }
  697.  
  698.  
  699.  
  700. /* Handle the "*** Done" command when reverse forwarding ends or the
  701.  * "*** LINKED to" command.
  702.  */
  703. int
  704. dostars (int argc, char *argv[], void *p)
  705. {
  706. struct mbx *m;
  707. int anony = 1;
  708. int founddigit = 0;
  709. int oldprivs;
  710. char *cp;
  711.  
  712.     m = (struct mbx *) p;
  713.  
  714.     /* Allow 'linked to' from anyone, but reset SYSOP priviledges
  715.      * when the sysop-password is not set !
  716.      * Also try to set the new call !
  717.      * Inspired by Kurt, wb5bbw
  718.      * Check for the strange TEXNET linked message !
  719.      * 920220 - WG7J
  720.      */
  721.     if ((argc >= 4) && !strcmp (argv[1], "linked") && !strcmp (argv[2], "to")) {
  722.         if (m->privs & NO_LINKEDTO) {
  723.             puts (Noperm);
  724. #ifdef GWTRACE
  725.             log (m->user, loglinkdenied, m->name);
  726. #endif
  727.             return 0;
  728.         }
  729. #ifdef GWTRACE
  730.         log (m->user, loglink, m->name, argv[3]);
  731. #endif
  732.         strncpy (m->name, argv[3], MBXLINE);
  733.         oldprivs = m->privs;    /*Save this !*/
  734.         /* Try to find the privileges of this user from the userfile */
  735.         if ((m->privs = userlogin (m->name, NULLCHAR, &m->path, MBXLINE,
  736.                        &anony)) == -1)
  737.             if ((m->privs = userlogin ("bbs", NULLCHAR, &m->path,
  738.                            MBXLINE, &anony)) == -1)
  739.                 if ((m->privs = userlogin ("anonymous", NULLCHAR,
  740.                     &m->path, MBXLINE, &anony)) == -1) {
  741.                     m->privs = 0;
  742.                     free (m->path);
  743.                     m->path = NULLCHAR;
  744.                 }
  745.         if (m->privs & EXCLUDED_CMD)
  746.             return domboxbye (0, NULLCHARP, p);
  747. #ifdef AX25
  748.         /* Set the call */
  749.         for (cp = m->name; *cp != '\0'; cp++)
  750.             if (isdigit ((int) *cp))
  751.                 break;
  752.         if (*cp != '\0')
  753.             founddigit = 1;
  754.         if ((setcall (m->call, m->name) == -1) || (!founddigit)) {
  755.             m->privs &= ~AX25_CMD;
  756.             m->privs &= ~NETROM_CMD;
  757.         }
  758. #else
  759.         m->privs &= ~AX25_CMD;
  760.         m->privs &= ~NETROM_CMD;
  761. #endif
  762.         /*Kill ssid in name, if any*/
  763.         if ((cp = strchr (m->name, '-')) != NULLCHAR)
  764.             *cp = '\0';
  765.         /*Check if sysop password is set,
  766.          *if not, disallow sysop privs no matter what !
  767.          */
  768.         if (*Mbpasswd == '\0')
  769.             m->privs &= ~SYSOP_CMD;
  770.         /*Check to see if any of NO_READ,NO_SEND or NO_3PARTY were set,
  771.          *if so, dis-allow those no matter what
  772.          *(so that users cannot get priviledges by issuing a ***linked)
  773.          * 920220 - WG7J
  774.          */
  775.         if (oldprivs & NO_SENDCMD)
  776.             m->privs |= NO_SENDCMD;
  777.         if (oldprivs & NO_READCMD)
  778.             m->privs |= NO_READCMD;
  779.         if (oldprivs & NO_3PARTY)
  780.             m->privs |= NO_3PARTY;
  781.  
  782.         tprintf (linkhello, m->name);
  783. #ifdef MAILCMDS
  784.         changearea (m, m->name, (int) 1);
  785. #endif
  786.         return 0;
  787.     }
  788.     if (argc > 1 && (m->sid & MBX_SID))    /* "*** Done" or similar */
  789.         return -2;
  790.     return -1;
  791. }
  792.  
  793.  
  794.  
  795. #if defined(GATECMDS) || defined(FOQ_CMDS)
  796. int
  797. dombtelnet (int argc, char *argv[], void *p)
  798. {
  799. struct mbx *m;
  800. int s, len, i;
  801. int nonampr = 0;
  802. char dsocket[MAXSOCKSIZE];
  803. struct sockaddr_in fsocket;
  804. short wasSecureTelnet;
  805.  
  806.     wasSecureTelnet = SecureTelnet;
  807.     SecureTelnet = 1;
  808.     m = (struct mbx *) p;
  809.     fsocket.sin_family = AF_INET;
  810.     if (argc < 3)
  811.         fsocket.sin_port = IPPORT_TELNET;
  812.     else    {
  813.         /* if m->stype == '+' we were called internally */
  814.         if (m->stype != '+' && (m->privs & NO_NON23))    {
  815.             tputs ("\nSorry, but you do not have permission to specify a non-standard telnet port!\n");
  816.             return 0;
  817.         }
  818.         fsocket.sin_port = (int16) atoip (argv[2]);
  819.     }
  820.  
  821.     if ((fsocket.sin_addr.s_addr = resolve (argv[1])) == 0) {
  822.         tprintf (Badhost, argv[1]);
  823.         /* Free m->startmsg if set ! - WG7J */
  824.         if (m->startmsg != NULLCHAR) {
  825.             free (m->startmsg);
  826.             m->startmsg = NULLCHAR;
  827.         }
  828.         return 0;
  829.     }
  830.     nonampr = (((fsocket.sin_addr.s_addr & 0xff000000LU) >> 24) != 44);
  831.  
  832.     if (AMPRonly && (m->privs & WAS_ANONY) && nonampr) {
  833.         tputs (ampronly_str);
  834.         /* Free m->startmsg if set ! - WG7J */
  835.         if (m->startmsg != NULLCHAR) {
  836.             free (m->startmsg);
  837.             m->startmsg = NULLCHAR;
  838.         }
  839.         return 0;
  840.     }
  841.     /* Only local telnets are are allowed to the unprivileged user */
  842.     /* The above is a security hole ! DO NOT allow this anymore ! - WG7J */
  843.  
  844.     /* If the first letter of the command is 'C', then it was
  845.      * the CALL,QUERY,OPERATOR or CONFERENCE command !
  846.      * Allow these, no matter what.
  847.      * This way, you can give access to the Internet callserver,
  848.      * but disable all other telnets - WG7J
  849.      */
  850.     if (wasSecureTelnet && *argv[0] != 'C') {
  851.         if ((nonampr && !(m->privs & TELNET_CMD)) || (!nonampr && !(m->privs & AMPR_CMD))) {
  852.             tputs (Noperm);
  853.             mail_error (telnetdenied, m->name, cmd_line (argc, argv, m->stype));
  854. #ifdef TUTOR
  855.             strcpy (m->line, "denied telnet");
  856.             mbscripthook (m, "denied.sys");
  857. #endif
  858.             /* Free m->starmsg if set ! - WG7J */
  859.             /* Shouldn't happen here, but just in case */
  860.             if (m->startmsg != NULLCHAR) {
  861.                 free (m->startmsg);
  862.                 m->startmsg = NULLCHAR;
  863.             }
  864.             return 0;
  865.         }
  866.     }
  867.     if ((s = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
  868.         tputs (Nosock);
  869.         /* Free m->starmsg if set ! - WG7J */
  870.         if (m->startmsg != NULLCHAR) {
  871.             free (m->startmsg);
  872.             m->startmsg = NULLCHAR;
  873.         }
  874.         return 0;
  875.     }
  876. #ifdef GWTRACE
  877.     log (m->user, logtelnet, m->name, argv[1], fsocket.sin_port);
  878. #endif
  879.     if (fsocket.sin_port == IPPORT_TTYLINK) {
  880.         m->startmsg = mallocw (80);
  881.         len = MAXSOCKSIZE;
  882.         i = getpeername (m->user, dsocket, &len);
  883.         sprintf (m->startmsg, incomingcall, m->name, i != -1 ? psocket (dsocket) : Hostname);
  884.     }
  885.     m->state = MBX_GATEWAY;
  886.     return gw_connect (m, s, (struct sockaddr *) &fsocket, SOCKSIZE);
  887. }
  888. #endif
  889.  
  890.  
  891.  
  892. #ifdef FOQ_CMDS
  893. int
  894. dombfinger (int argc, char *argv[], void *p)
  895. {
  896. struct mbx *m;
  897. char *host, *user = NULLCHAR, buf[8], *newargv[3], buf2[2];
  898.  
  899.     if (argc > 2) {
  900.         tputs (finger_usage);
  901.         return -1;
  902.     }
  903.     host = Hostname;
  904.     if (argc == 2) {
  905.         if ((host = strchr (argv[1], '@')) != NULLCHAR) {
  906.             *host = '\0';
  907.             host++;
  908.         } else
  909.             host = Hostname;
  910.         user = argv[1];
  911.     }
  912.     m = (struct mbx *) p;
  913.     m->startmsg = mallocw (80);
  914.     if (user != NULLCHAR)
  915.         sprintf (m->startmsg, "%s\n", user);
  916.     else
  917.         strcpy (m->startmsg, "\n");
  918.     buf2[0] = 't';
  919.     buf2[1] = 0;
  920.     newargv[0] = buf2;
  921.     newargv[1] = host;
  922.     sprintf (buf, "%d", IPPORT_FINGER);
  923.     newargv[2] = buf;
  924.     SecureTelnet = 0;
  925.     m->stype = '+';
  926.     return dombtelnet (3, newargv, p);
  927. }
  928. #endif
  929.  
  930.  
  931.  
  932. extern int Mbconverse;
  933.  
  934.  
  935.  
  936. #ifdef  CONVERS
  937. int
  938. dombconvers (int argc, char *argv[], void *p)
  939. {
  940. struct mbx *m;
  941. int channel = -1;
  942. struct session *sp;
  943.  
  944.     m = (struct mbx *) p;
  945.  
  946.     if (!Mbconverse) {
  947.         tputs (confnotenabled);
  948.         return 0;
  949.     }
  950.     if (m->privs & NO_CONVERS) {
  951.         tputs (Noperm);
  952.         mail_error (convdenied, m->name);
  953. #ifdef TUTOR
  954.         strcpy (m->line, "denied converse");
  955.         mbscripthook (m, "denied.sys");
  956. #endif
  957.         return 0;
  958.     }
  959.     if (argc != 1)
  960.         channel = atoi (argv[1]);
  961. #ifdef GWTRACE
  962.     log (m->user, logconf, m->name);
  963. #endif
  964.     m->state = MBX_CONVERS;
  965.     usflush (Curproc->output);
  966.     if (Current->type == 1)
  967.         tprintf ("%c%c", IAC, CLEARSCREEN);    /* sets Current->split */
  968.     sp = Current;
  969.     kwait (NULL);
  970.     mbox_converse (m->user, m->name, channel, m);
  971.     if (sp->split) {
  972.         usflush (Curproc->output);
  973.         tprintf ("%c%c", IAC, CLEARSPLIT);    /* clears Current->split */
  974.         usflush (Curproc->output);
  975.         sp->split = 0;
  976.     }
  977.     return 0;
  978. }
  979. #endif
  980.  
  981.  
  982.  
  983. #ifdef TUTOR
  984. extern int Sinfo;
  985. #endif
  986.  
  987.  
  988.  
  989. int
  990. dombhelp (int argc, char *argv[], void *p)
  991. {
  992. char buf[255];
  993. FILE *fp;
  994. struct mbx *m;
  995.  
  996.     m = (struct mbx *) p;
  997.  
  998. #ifdef MBFWD
  999.     if ((m->stype == 'F') && (m->privs & SYSOP_CMD)) {
  1000.         forwardingSummary ();
  1001.         return 0;
  1002.     }
  1003. #endif
  1004.     if (m->stype == 'H')
  1005.         return (doipheard (argc, argv, p));
  1006.     if (m->stype == 'P')
  1007.         return (dombiproute (argc, argv, p));
  1008.  
  1009.     buf[0] = '\0';
  1010.     /* check for "?" and "help" here */
  1011.     if (*argv[0] == '?' || *argv[0] == 'h') {
  1012.         bbscolorcls (m);
  1013.         bbscolorchange (m, "07");
  1014.         (void) dombxhelp (argc, argv, p);
  1015.         if (*argv[0] == '?' && argc == 1) {
  1016.             bbscolorchange (m, "0B");
  1017.             tputs (Alsomenu);
  1018.             tputs (Alsomenu2);
  1019.             if (m->privs & SYSOP_CMD)
  1020.                 tputs (Sysopmenu);
  1021.             bbscolorchange (m, "09");
  1022.             sprintf (buf, "%s/help.hlp", Helpdir);
  1023.             goto also;
  1024.         }
  1025.         return 0;
  1026.     }
  1027. #ifdef TUTOR
  1028.     if (Sinfo != -1) {
  1029.         log (m->user, logtutor, m->name);
  1030.         m->state = MBX_TUTOR;
  1031.         tutorserv (m->name, m, 1, m->usecolor, 0);
  1032.     } else {
  1033. #endif
  1034.         tprintf (Nosversion, Version, Compiled);
  1035.         tprintf ((BbsUsers == 1) ? Only : CurUsers, BbsUsers);
  1036.         sprintf (buf, "%s/sysinfo.hlp", Helpdir);
  1037. also:
  1038.         if ((fp = fopen (buf, READ_TEXT)) != NULLFILE) {
  1039.             (void) sendfile (fp, Curproc->output, ASCII_TYPE, 0);
  1040.             (void) fclose (fp);
  1041.         } else {
  1042.             if (argc > 1 && *argv[0] == 'h')
  1043.                 tputs (nohelp);
  1044.         }
  1045. #ifdef TUTOR
  1046.     }
  1047. #endif
  1048.     return 0;
  1049. }
  1050.  
  1051.  
  1052.  
  1053. #ifdef MAILCMDS
  1054. extern char Badmsg[];
  1055. extern char Nomail[];
  1056.  
  1057.  
  1058.  
  1059. /* Move messages from current area to another */
  1060. int
  1061. dombmovemail (int argc, char *argv[], void *p)
  1062. {
  1063. int num, i;
  1064. int movebuf[NARG];
  1065. char *to;
  1066. struct mbx *m;
  1067. char buf[MBXLINE];
  1068. FILE *Mfile;        /* file to move to */
  1069. struct let *cmsg;
  1070. long size;
  1071. int thisone, wrcntr, sawempty;
  1072. struct let lt;
  1073. char *tmpbuf;
  1074. int msg, maxmsg;
  1075.  
  1076.     m = (struct mbx *) p;
  1077.  
  1078.     if (argc == 1) {
  1079.         char const *which;
  1080.  
  1081.         which = (m->stype == 'M') ? "move" : (m->stype == 'W') ? "write" : "copy";
  1082.         tprintf ("Syntax: M%c area - %s current message\n        M%c n1 [n2...] %s - %s message n1 (n2...)\n",
  1083.              m->stype, which, m->stype, (m->stype == 'W') ? "filename" : "area", which);
  1084.         return 0;
  1085.     }
  1086.     if (m->mfile == NULLFILE) {
  1087.         tputs (Nomail);
  1088.         return 0;
  1089.     }
  1090.     if (argc == 2) {
  1091.         /* NO message #, use current message */
  1092.         num = 1;
  1093.         to = argv[1];
  1094.         movebuf[0] = m->current;
  1095.     } else {
  1096.         /* Scan all message # to move */
  1097.         num = 0;
  1098.         for (i = 1; i < argc - 1; i++) {
  1099.             tmpbuf = strchr (argv[i], '-');
  1100.             msg = atoi (argv[i]);
  1101.             if (tmpbuf == NULLCHAR)
  1102.                 maxmsg = msg;
  1103.             else
  1104.                 maxmsg = atoi (++tmpbuf);
  1105.             if (!msg || maxmsg < msg) {
  1106.                 tprintf (Badmsg, argv[i]);
  1107.                 continue;
  1108.             }
  1109.             for (; msg <= maxmsg; msg++) {
  1110.                 if (msg > m->nmsgs)
  1111.                     tprintf (Badmsg, msg);
  1112.                 else
  1113.                     movebuf[num++] = msg;
  1114.                 if (num == NARG)
  1115.                     break;
  1116.             }
  1117.             if (num == NARG)
  1118.                 tprintf (onlyfirst, NARG);
  1119.         }
  1120.         to = argv[argc - 1];
  1121.     }
  1122.     if (m->stype != 'W')
  1123.         (void) nntp_name_expansion (to);
  1124.  
  1125.     /* Now try to lock the destination file, if not a write */
  1126.     if (m->stype != 'W')
  1127.         if (mlock (Mailspool, to) == -1) {
  1128.             tprintf (cannotlock, to);
  1129.             return 0;
  1130.         }
  1131.     /* open the destination file for appending */
  1132.     if (m->stype == 'W') {
  1133.         char *pp;
  1134.  
  1135.         pp = permtest (m->path, m->privs, to, STOR_CMD, NULLCHAR, 0);
  1136.         if (!pp)
  1137.             return 0;
  1138.         strncpy (buf, pp, MBXLINE);
  1139.         free (pp);
  1140.     } else
  1141.         sprintf (buf, "%s/%s.txt", Mailspool, to);
  1142.     if ((Mfile = fopen (buf, "a")) == NULLFILE) {
  1143.         tprintf ("Can't open '%s'\n", buf);
  1144.         if (m->stype != 'W')
  1145.             rmlock (Mailspool, to);
  1146.         return 0;
  1147.     }
  1148.  
  1149.     /* Okay, let's do the work */
  1150.     for (i = 0; i < num; i++) {
  1151.         thisone = movebuf[i];    /*lint !e644 */
  1152.         cmsg = &m->mbox[thisone];
  1153.         /* find start of this message */
  1154.         fseek (m->mfile, cmsg->start, 0);
  1155.         size = cmsg->size;
  1156.         (void) fflush (Mfile);
  1157.         lt.size = cmsg->size;
  1158.         lt.bid = cmsg->bid;
  1159.         lt.status = 0;
  1160.         lt.start = (long) filelength (fileno (Mfile));
  1161.         wrcntr = 0;
  1162.         sawempty = 0;
  1163.  
  1164.         /* now read this message */
  1165.         while (size > 0 && fgets (buf, MBXLINE, m->mfile) != NULLCHAR) {
  1166.             kwait (NULL);
  1167.             if (!sawempty && strlen (buf) == 1)    /* "\n" - dunno about DOS */
  1168.                 sawempty = 1;
  1169.             if (m->stype == 'W' && !sawempty)    /* trim headers on "MW" */
  1170.                 trimrightCR (buf);
  1171.             if (m->stype != 'W' || wrcntr > 2)
  1172.                 fputs (buf, Mfile);
  1173.             wrcntr += 1;
  1174.             size -= (long) strlen (buf);
  1175.         }
  1176. #ifdef USERLOG
  1177.         if (m->stype == 'M' || m->stype == 'C') {
  1178.             updateCtl (to, <);
  1179.         }
  1180. #endif
  1181.         /* delete this message, if moving */
  1182.         if (m->stype == 'M') {
  1183.             cmsg->status |= BM_DELETE;
  1184.             cmsg->status &= ~BM_ONHOLD;
  1185.             statusCtl (m->area, "ctl", cmsg, thisone, 0);
  1186.             if (!issysarea (m->area))
  1187.                 m->change |= CHG_DELETE;
  1188.         }
  1189.         tprintf (message, thisone, (m->stype == 'M') ? "moved" : (m->stype == 'W') ? "written" : "copied");
  1190.     }
  1191.     (void) fclose (Mfile);
  1192.     if (m->stype != 'W') {
  1193. #ifdef ALERTMONITOR
  1194.         alertarea (to);
  1195. #endif
  1196.         rmlock (Mailspool, to);
  1197.     }
  1198.     return 0;
  1199. }
  1200. #endif
  1201.  
  1202.  
  1203.  
  1204. static void
  1205. expertstat (struct mbx *m)
  1206. {
  1207. char const *p;
  1208. int32 flag;
  1209.  
  1210.     switch (m->stype) {
  1211.         case 'M':
  1212.             tprintf (moreafter, m->morerows);
  1213.             return;
  1214.         case 'A':
  1215.             p = areaadded;
  1216.             flag = m->sid & MBX_AREA;
  1217.             break;
  1218.         case 'N':
  1219.             p = nameadded;
  1220.             flag = m->sid & MBX_NRID;
  1221.             break;
  1222.         case 'S':
  1223.             p = newscanlogin;
  1224.             flag = m->sid & MBX_STATS;
  1225.             break;
  1226.         case 'G':
  1227.             p = usaANSI;
  1228.             flag = m->sid & MBX_GFX;
  1229.             break;
  1230.         case 'P':
  1231.             tprintf (permissionlevel, m->privs, m->privs);
  1232.             return;
  1233. #ifdef DELEGATE
  1234.         case 'D':
  1235.             display_delegation (m->name);
  1236.             p = fwddelegation;
  1237.             flag = m->sid & MBX_DELEGATE;
  1238.             break;
  1239. #endif
  1240. #ifdef LZW
  1241.         case 'C':
  1242.             p = usecompressed;
  1243.             flag = m->sid & MBX_TNOS;
  1244.             break;
  1245. #endif
  1246.         case 'X':
  1247.         case ' ':
  1248.             p = expertprompts;
  1249.             flag = m->sid & MBX_EXPERT;
  1250.             break;
  1251.         default:
  1252.             return;
  1253.     }
  1254.     tprintf ("%s: o%s\n", p, (flag) ? "n" : "ff");
  1255.     return;
  1256. }
  1257.  
  1258.  
  1259.  
  1260. static int
  1261. dombgetall (struct mbx *m)
  1262. {
  1263. char *args[2];
  1264. char buf[4];
  1265.  
  1266.     tprintf (usersettings, m->name);
  1267.     m->stype = 'M';            expertstat (m);
  1268.     m->stype = 'A';            expertstat (m);
  1269.     m->stype = 'N';            expertstat (m);
  1270.     m->stype = 'S';            expertstat (m);
  1271.     m->stype = 'G';            expertstat (m);
  1272.     m->stype = 'C';            expertstat (m);
  1273. #ifdef LZW
  1274.     m->stype = 'X';            expertstat (m);
  1275. #endif
  1276.     m->stype = 'P';            expertstat (m);
  1277.     strcpy (buf, "F");
  1278.     args[1] = buf;
  1279.     (void) dombget (2, args, m);
  1280.     strcpy (buf, "Si");
  1281.     args[1] = buf;
  1282.     (void) dombget (2, args, m);
  1283. #ifdef DELEGATE
  1284.     strcpy (buf, "D");
  1285.     args[1] = buf;
  1286.     (void) dombget (2, args, m);
  1287. #endif
  1288.     tputs (useSET);
  1289.     return 0;
  1290. }
  1291.  
  1292.  
  1293.  
  1294. int
  1295. dombget (int argc, char *argv[], void *p)
  1296. {
  1297. struct mbx *m;
  1298. int cnt;
  1299.  
  1300.     if (argc == 1)
  1301.         return (dombgetall (p));
  1302.     m = (struct mbx *) p;
  1303.     m->stype = (char) toupper (*argv[1]);
  1304.     if (m->stype != 'F' && strnicmp (argv[1], "Si", 2)) {
  1305.         expertstat (m);
  1306.         return 0;
  1307.     }
  1308.     sprintf (m->line, "%s/%s%s", (m->stype == 'F') ? FingerDir : Signature, m->name, (m->stype == 'S') ? ".sig" : "");
  1309.     tprintf (getheader, (m->stype == 'F') ? "Finger" : "Signature");
  1310.     cnt = DisplayFile (m->line, m->user);
  1311.     tprintf (gettrailer, (cnt) ? "End of" : "No", (m->stype == 'F') ? "Finger" : "Signature");
  1312.     return 0;
  1313. }
  1314.  
  1315.  
  1316.  
  1317. #ifdef MAILCMDS
  1318. int
  1319. doreply (int argc, char *argv[], void *p)
  1320. {
  1321. register struct mbx *m;
  1322.  
  1323.     m = (struct mbx *) p;
  1324.     m->stype = 'R';
  1325.     return (dosend (argc, argv, p));
  1326. }
  1327. #endif
  1328.  
  1329.  
  1330.  
  1331. int
  1332. douser (int argc, char *argv[], void *p)
  1333. {
  1334. register struct mbx *m;
  1335.  
  1336.     m = (struct mbx *) p;
  1337.     m->stype = 'L';
  1338.     return (dombusers (argc, argv, p));
  1339. }
  1340.  
  1341.  
  1342.  
  1343. #ifdef TIPMAIL
  1344. int
  1345. dombslip (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  1346. {
  1347. register struct mbx *m;
  1348.  
  1349.     m = (struct mbx *) p;
  1350.     if (m->type != TIP) {
  1351.         tputs (noconfig);
  1352.         return (0);
  1353.     }
  1354.     if (m->privs & NO_SLIP) {
  1355.         tputs (Noperm);
  1356.         return 0;
  1357.     }
  1358.     suspendTipMail (m);
  1359.     return -2;
  1360. }
  1361. #endif
  1362.  
  1363.  
  1364.  
  1365. int
  1366. dombexpert (int argc, char *argv[], void *p)
  1367. {
  1368. struct mbx *m;
  1369. #ifdef LZW
  1370. struct usock *up;
  1371. #endif
  1372.  
  1373.     m = (struct mbx *) p;
  1374.  
  1375.     switch (m->stype) {
  1376.         case 'M':
  1377.             if (argc == 1) {
  1378.                 tprintf (moreafter, m->morerows);
  1379.                 return 0;
  1380.             } else {
  1381.                 m->morerows = atoi (argv[1]);
  1382.             }
  1383.             break;
  1384.         case 'A':
  1385.             m->sid ^= MBX_AREA;
  1386.             break;
  1387.         case 'G':
  1388.             m->sid ^= MBX_GFX;
  1389.             m->usecolor ^= 1;
  1390.             break;
  1391.         case 'N':
  1392.             m->sid ^= MBX_NRID;
  1393.             break;
  1394.         case 'S':
  1395.             m->sid ^= MBX_STATS;
  1396.             break;
  1397. #ifdef DELEGATE
  1398.         case 'D':
  1399.             if (Mbdelegate) {
  1400.                 m->sid ^= MBX_DELEGATE;
  1401.                 if (m->sid & MBX_DELEGATE)
  1402.                     setup_delegate (m);
  1403.                 else
  1404.                     clear_delegate (m);
  1405.             } else {
  1406.                 tputs (delegationdisabled);
  1407.                 m->sid &= ~MBX_DELEGATE;
  1408.                 return 0;
  1409.             }
  1410.             break;
  1411. #endif
  1412. #ifdef LZW
  1413.         case 'C':
  1414.             m->sid ^= MBX_TNOS;
  1415.             up = itop (m->user);
  1416.             if ((m->sid & MBX_TNOS) || (up->zout != NULLLZW))
  1417.                 togglelzw (m->user, m->sid & MBX_TNOS);
  1418.             break;
  1419. #endif
  1420.         case ' ':
  1421.         case 'X':
  1422.             m->sid ^= MBX_EXPERT;
  1423.             break;
  1424.         default:
  1425.             return 0;
  1426.     }
  1427.     m->update = 1;
  1428.     expertstat (m);
  1429.     return 0;
  1430. }
  1431.  
  1432.  
  1433.  
  1434. int
  1435. dombexpand (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  1436. {
  1437. struct list *ap, *list;
  1438. char *arg, *orig, *newaddr, buf[LINELEN];
  1439. int loopindex;
  1440.  
  1441.     tprintf (expandsto, argv[1]);
  1442.     arg = argv[1];
  1443.     list = NULLLIST;
  1444.     orig = strdup (arg);
  1445.     /* rewrite address if possible */
  1446.     if ((newaddr = rewrite_address (arg, 0)) != NULLCHAR)
  1447.         if (strcmp (newaddr, arg) == 0) {
  1448.             free (newaddr);
  1449.             newaddr = NULLCHAR;
  1450.         } else {
  1451.             strncpy (buf, newaddr, LINELEN);
  1452.             arg = buf;
  1453.         }
  1454.     list = NULLLIST;
  1455.     (void) expandalias (&list, arg, orig);
  1456.     free (orig);
  1457.     if (list == NULLLIST) {
  1458.         tprintf ("nothing");
  1459.         return 0;
  1460.     }
  1461.     if (strcmp (list->val, arg) == 0 && list->next == NULLLIST)
  1462.         if (newaddr == NULLCHAR) {
  1463.             tprintf ("'%s'\n", arg);
  1464.             del_list (list);
  1465.             return 0;
  1466.         }
  1467.     ap = list;
  1468.     loopindex = 0;
  1469.     while (ap->next != NULLLIST) {
  1470.         if (!(loopindex++ % 2))
  1471.             tputc ('\n');
  1472.         tputs ("     ");
  1473.         tprintf ("%-32.32s", ap->val);
  1474.         ap = ap->next;
  1475.     }
  1476.     tprintf ("%s     %s\n", (loopindex % 2) ? "" : "\n", ap->val);
  1477.     del_list (list);
  1478.     free (newaddr);
  1479.     return 0;
  1480. }
  1481.  
  1482.  
  1483.  
  1484. #ifdef MBFWD
  1485. int
  1486. dombroute (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  1487. {
  1488. char *arg, *newaddr;
  1489. #if 0
  1490. char buf[LINELEN];
  1491. #endif
  1492. int k, loopindex;
  1493.  
  1494.     arg = argv[1];
  1495.     if (!arg) {
  1496.         tputs (noaddress);
  1497.         return 1;
  1498.     }
  1499.     tprintf (addressroutes, argv[1]);
  1500.     /* rewrite address if possible */
  1501.     if ((newaddr = rewrite_address (arg, 0)) == NULLCHAR)
  1502.         newaddr = strdup (argv[1]);
  1503.     for (loopindex = 0, k = 0; k < Numfwds; k++)
  1504.         if (AREAlookup (newaddr, k)) {
  1505.             if (!(loopindex++ % 3))
  1506.                 tputs ("\n   ");
  1507.             tprintf ("%-25.25s", MyFwds[k].name);
  1508.         }
  1509.     tputc ('\n');
  1510.     free (newaddr);
  1511.     return 0;
  1512. }
  1513. #endif
  1514.  
  1515.  
  1516.  
  1517. #ifdef RMAIL
  1518. int
  1519. dombrmail (int argc, char *argv[], void *p)
  1520. {
  1521. int orgchange;
  1522. struct mbx *m;
  1523. char *cp;
  1524.  
  1525.     m = (struct mbx *) p;
  1526.     if (!(m->sid & MBX_SID)) {    /* not available to BBSs */
  1527.         orgchange = m->change;
  1528.         m->change = -1;
  1529.         m->stype = 'C';
  1530.         cp = mallocw (strlen (argv[1]) + 8);
  1531.         sprintf (cp, "rmail@%s", argv[1]);
  1532.         argv[1] = cp;
  1533.         (void) dosend (argc, argv, p);
  1534.         m->change = orgchange;
  1535.         free (cp);
  1536.     }
  1537.     return 0;
  1538. }
  1539. #endif
  1540.  
  1541.  
  1542.  
  1543. #ifdef LZW
  1544. void
  1545. togglelzw (int soc, int mode)
  1546. {
  1547. struct usock *up;
  1548.  
  1549.     if ((up = itop (soc)) == NULLUSOCK)
  1550.         return;
  1551.     tprintf ("%c%c%c%c", IAC, COMPRESSED, (Lzwmode) ? 'f' : 'c', Lzwbits);
  1552.     usflush (soc);
  1553.     if (mode) {
  1554.         lzwinit (soc, Lzwbits, Lzwmode);
  1555.         up->zin->maxbits = -1;
  1556.     } else
  1557.         lzwfree (up);
  1558.     usflush (soc);
  1559.     if (socklen (soc, 0))    /* discard any remaining input */
  1560.         (void) recv_mbuf (soc, NULL, 0, NULLCHAR, 0);
  1561. }
  1562. #endif
  1563.  
  1564.  
  1565.  
  1566. int
  1567. dombset (int argc, char *argv[], void *p)
  1568. {
  1569. struct mbx *m;
  1570.  
  1571.     m = (struct mbx *) p;
  1572.     m->stype = (char) toupper (*argv[1]);
  1573.     if (!strnicmp (argv[1], "Si", 2))
  1574.         m->stype = '$';
  1575.     if (m->stype == 'F' || m->stype == '$')
  1576.         return (dombupload (argc, argv, p));
  1577.     else
  1578.         return (dombexpert (argc - 1, &argv[1], p));
  1579. }
  1580.  
  1581.  
  1582.  
  1583. #ifdef USERLOG
  1584.  
  1585. /* Routine for quickly checking an area for messages that are new to this user.
  1586.    This routine reads the area.ctl files, which contains a bid for each message.  */
  1587.  
  1588. static int
  1589. quickstat (register struct mbx *m, char *area)
  1590. {
  1591. long last, newlast, lastone;
  1592. char oldarea[64], buf[256];
  1593. FILE *fp;
  1594. register int retval = 0;
  1595.  
  1596.     last = m->lastread;
  1597.     newlast = m->newlastread;
  1598.     m->lastread = 0;
  1599.     strncpy (oldarea, m->area, 64);
  1600.     strncpy (m->area, area, 64);
  1601.     (void) strlwr (m->area);
  1602.     (void) nntp_name_expansion (m->area);
  1603.     /* only read last read message-id if current area is a public area
  1604.      * and not 'help' or area starts with 'sys'
  1605.      * read in all cases if a SYSOP
  1606.      */
  1607.  
  1608.     if ((stricmp (area, "help") && isarea (area)) || !strnicmp (m->area, "sys", 3) || (m->privs & SYSOP_CMD))
  1609.         getlastread (m);
  1610.     kwait (NULL);
  1611.     lastone = m->lastread;
  1612.     m->lastread = last;
  1613.     m->newlastread = newlast;
  1614.     sprintf (buf, "%s/control/%s.ctl", Mailspool, m->area);
  1615.     if ((fp = fopen (buf, READ_BINARY)) != NULLFILE) {
  1616.         struct let lt;
  1617.         long size;
  1618.         size = (long) (filelength (fileno (fp)) - sizeof (struct let));
  1619.  
  1620.         fseek (fp, size, SEEK_SET);
  1621.         (void) fread (<, sizeof (struct let), 1, fp);
  1622.  
  1623.         (void) fclose (fp);
  1624.         if (lt.bid > lastone)
  1625.             retval = 1;
  1626.     }
  1627.     strncpy (m->area, oldarea, 64);
  1628.     kwait (NULL);
  1629.     return retval;
  1630. }
  1631.  
  1632.  
  1633.  
  1634. void
  1635. quickscan (struct mbx *m, int olduser, int usename)
  1636. {
  1637. char const *cp;
  1638. char *cp2;
  1639. FILE *fp;
  1640. char buf[MBXLINE];
  1641. char out[MBXLINE];
  1642. char const *initmsg;
  1643. int found = 0, length = 3;
  1644.  
  1645.     cp = Arealist;
  1646.     if ((m->privs & SYSOP_CMD) && (!access (AreaSlist, 0)))
  1647.         cp = AreaSlist;
  1648.     if ((fp = fopen (cp, READ_TEXT)) == NULLFILE)
  1649.         return;
  1650.     if (olduser)
  1651.         initmsg = unreadmessages;
  1652.     else
  1653.         initmsg = newmessages;
  1654.     strcpy (out, "   ");
  1655.     while (fgets (buf, MBXLINE, fp) != NULLCHAR) {
  1656.         kwait (NULL);
  1657.         if (isalnum (buf[0])) {    /* skip comments */
  1658.             if ((cp2 = strpbrk (buf, " \t\n\r")) != NULLCHAR)
  1659.                 *cp2 = '\0';
  1660.             /*            statarea (m, buf, &total, &new, &hold, 0);
  1661.             if (new)    {        */
  1662.             if (quickstat (m, buf)) {
  1663.                 if (!found) {
  1664.                     tprintf (initmsg, (usename) ? m->name : "You", (usename) ? "s" : "ve");
  1665.                     found++;
  1666.                 }
  1667.                 length += (int) (strlen (buf) + 2);
  1668.                 strcat (out, buf);
  1669.                 strcat (out, "  ");
  1670.             }
  1671.             if (length > 70) {
  1672.                 tputs (out);
  1673.                 tputc ('\n');
  1674.                 out[3] = 0;
  1675.                 length = 3;
  1676.             }
  1677.         }
  1678.     }
  1679.     if (length != 3) {
  1680.         tputs (out);
  1681.         tputc ('\n');
  1682.     }
  1683.     (void) fclose (fp);
  1684.     if (!found)
  1685.         tprintf (nounreadmessages, (usename) ? m->name : "You", (usename) ? "is" : "are");
  1686. }
  1687. #endif
  1688.  
  1689.  
  1690.  
  1691. #if defined(FOQ_CMDS)
  1692. int
  1693. dombquote (int argc, char *argv[], void *p)
  1694. {
  1695. char *host, buf[8], *newargv[3], buf2[2];
  1696. struct mbx *m;
  1697.  
  1698.     m = (struct mbx *)p;
  1699.     host = Hostname;
  1700.     if (argc == 2)
  1701.         host = argv[1];
  1702.     buf2[0] = 't';
  1703.     buf2[1] = 0;
  1704.     newargv[0] = buf2;
  1705.     newargv[1] = host;
  1706.     sprintf (buf, "%d", IPPORT_QUOTE);
  1707.     newargv[2] = buf;
  1708.     SecureTelnet = 0;
  1709.     m->stype = '+';
  1710.     return dombtelnet (3, newargv, p);
  1711. }
  1712. #endif
  1713.  
  1714.  
  1715.  
  1716. static void
  1717. informGroup (
  1718. char *action OPTIONAL,
  1719. char *group,
  1720. char *user,
  1721. char *buf,
  1722. FILE *old,
  1723. FILE *new,
  1724. FILE *in
  1725. ) {
  1726. char subj[68], *cp;
  1727.  
  1728.     sprintf (subj, inform_str, user, group);
  1729.     while (fgets (buf, 50, old) != NULLCHAR) {
  1730.         fputs (buf, new);
  1731.         if (*buf != ' ')
  1732.             break;
  1733.         if (buf[strlen (buf) - 2] == 'I') {
  1734.             if ((cp = strchr (&buf[1], ' ')) != NULLCHAR)
  1735.                 *cp = 0;
  1736.             if (in)
  1737.                 rewind (in);
  1738.             (void) rdaemon (in, NULLCHAR, NULLCHAR, &buf[1], subj, 'P', 0);
  1739.         }
  1740.     }
  1741. }
  1742.  
  1743.  
  1744.  
  1745. int
  1746. isgroup (char *group)
  1747. {
  1748. FILE *old;
  1749. register len, retval = 0;
  1750. char buf[80];
  1751.  
  1752.     if (!group)
  1753.         return 0;
  1754.     len = (int) strlen (group);
  1755.  
  1756.     if ((old = fopen (Group, UPDATE_TEXT)) == NULLFILE)
  1757.         return 0;
  1758.     while (fgets (buf, 80, old) != NULLCHAR) {
  1759.         if (!strnicmp (buf, group, (unsigned) len) && buf[len] == ':') {
  1760.             retval = 1;
  1761.             break;
  1762.         }
  1763.     }
  1764.     (void) fclose (old);
  1765.     return retval;
  1766. }
  1767.  
  1768.  
  1769.  
  1770. int
  1771. groupcommand (
  1772. char *action,
  1773. char *group,
  1774. char *user,
  1775. int local,
  1776. FILE **out,
  1777. FILE *in
  1778. ) {
  1779. FILE *new, *old;
  1780. char *newname, *cp;
  1781. int found = 0, retval = 0;
  1782. char which, buf[80], subj[68];
  1783. unsigned len;
  1784.  
  1785.     if ((old = fopen (Group, UPDATE_TEXT)) == NULLFILE)
  1786.         if ((old = fopen (Group, CREATE_TEXT)) == NULLFILE)
  1787.             return 0;
  1788.     newname = (char *) mallocw (strlen (Group) + 5);
  1789.     sprintf (newname, "%s.new", Group);
  1790.     if ((new = fopen (newname, CREATE_TEXT)) == NULLFILE) {
  1791.         (void) fclose (old);
  1792.         free (newname);
  1793.         return 0;
  1794.     }
  1795.     *action = (char) tolower (*action);
  1796.     if (*action == 'l') {    /* list groups */
  1797.         if (!local)
  1798.             fprintf (new, groupindex);
  1799.         while (fgets (buf, 50, old) != NULLCHAR) {
  1800.             if (*buf != ' ' && (cp = strchr (buf, ':')) != 0) {
  1801.                 *cp++ = '\n';
  1802.                 *cp = 0;
  1803.                 if (!local)
  1804.                     fputs (buf, new);
  1805.                 else
  1806.                     tputs (buf);
  1807.             }
  1808.         }
  1809.         if (!local) {
  1810.             rewind (new);
  1811.             strcpy (subj, "GROUP LISTING");
  1812.             (void) rdaemon (new, NULLCHAR, NULLCHAR, user, subj, 'P', 0);
  1813.         }
  1814.         retval = 1;
  1815.         goto confuzed;
  1816.     }
  1817.     if (group == NULLCHAR)
  1818.         goto confuzed;
  1819.  
  1820.     len = strlen (group);
  1821.  
  1822.     if (*action != 'a') {
  1823.         while (fgets (buf, 50, old) != NULLCHAR) {
  1824.             if (!strnicmp (buf, group, len) && buf[len] == ':') {
  1825.                 found = 1;
  1826.                 break;
  1827.             }
  1828.             fputs (buf, new);
  1829.         }
  1830.         if (!found)
  1831.             goto confuzed;
  1832.         if (*action != 'd')
  1833.             fputs (buf, new);
  1834.     }
  1835.     switch (tolower (*action)) {
  1836.         case 'a':
  1837.             fprintf (new, "%s:\n\n", group);
  1838.             break;
  1839.         case 'i':
  1840.             fprintf (new, " %s I\n", user);
  1841.             break;
  1842.         case 's':
  1843.             fprintf (new, " %s S\n", user);
  1844.             rip (buf);
  1845.             if (local)
  1846.                 (void) DisplayFile (&buf[len + 2], Curproc->output);
  1847.             else
  1848.                 *out = fopen (&buf[len + 2], READ_TEXT);
  1849.             informGroup (action, group, user, buf, old, new, in);
  1850.             break;
  1851.         case 'u':
  1852.             len = strlen (user);
  1853.             which = (char) ((strlen (action) < 3) ? 's' : tolower (action[2]));
  1854.             while (fgets (buf, 50, old) != NULLCHAR) {
  1855.                 if (*buf != ' ') {
  1856.                     fputs (buf, new);
  1857.                     break;
  1858.                 }
  1859.                 if (strnicmp (&buf[1], user, (unsigned) len) ||
  1860.                     tolower (buf[strlen (buf) - 2]) != which)
  1861.                     fputs (buf, new);
  1862.                 else
  1863.                     break;
  1864.             }
  1865.             break;
  1866.         case 'd':
  1867.             while (fgets (buf, 50, old) != NULLCHAR)
  1868.                 if (*buf != ' ') {
  1869.                     if (*buf != '\n')
  1870.                         fputs (buf, new);
  1871.                     break;
  1872.                 }
  1873.             break;
  1874.         default:
  1875.             goto confuzed;
  1876.     }
  1877.     while (fgets (buf, 50, old) != NULLCHAR)
  1878.         fputs (buf, new);
  1879.     (void) fclose (new);
  1880.     (void) fclose (old);
  1881.     unlink (Group);
  1882.     (void) rename (newname, Group);
  1883.     free (newname);
  1884.     return 1;
  1885.  
  1886. confuzed:
  1887.     (void) fclose (new);
  1888.     (void) fclose (old);
  1889.     unlink (newname);
  1890.     free (newname);
  1891.     return retval;
  1892. }
  1893.  
  1894.  
  1895.  
  1896. int
  1897. dombgroup (int argc, char *argv[], void *p)
  1898. {
  1899. struct mbx *m;
  1900. char cmd;
  1901. int retval = 1;
  1902.  
  1903.     m = (struct mbx *) p;
  1904.  
  1905.     cmd = (char) tolower (*argv[1]);
  1906.     if (cmd != 's' && cmd != 'u' && cmd != 'l' && (m->privs == -1 || !(m->privs & SYSOP_CMD)))
  1907.         retval = 0;
  1908.  
  1909.     if (!retval || (cmd != 'l' && argc < 3) || !groupcommand (argv[1], (argc > 2) ? argv[2] : NULLCHAR, (argc > 3 && m->privs & SYSOP_CMD) ? argv[3] : m->name, 1, (FILE **) 0, (FILE *) 0))
  1910.         tputs ("Denied!\n");
  1911.     else
  1912.         tputs ("Approved!\n");
  1913.     return 0;
  1914. }
  1915.  
  1916.  
  1917.  
  1918. #ifdef TUTOR
  1919. extern int Stutor, Snews;
  1920.  
  1921. int
  1922. dombtutor (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  1923. {
  1924. struct mbx *m;
  1925.  
  1926.     m = (struct mbx *) p;
  1927.  
  1928.     if (Stutor == -1) {
  1929.         tputs ("Tutorial server not enabled\n");
  1930.         return 0;
  1931.     }
  1932.     log (m->user, logtutor, m->name);
  1933.     m->state = MBX_TUTOR;
  1934.     tutorserv (m->name, m, 0, m->usecolor, 0);
  1935.     return 0;
  1936. }
  1937.  
  1938.  
  1939.  
  1940. int
  1941. dombnews (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  1942. {
  1943. struct mbx *m;
  1944.  
  1945.     m = (struct mbx *) p;
  1946.  
  1947.     if (Snews == -1) {
  1948.         tputs (newsdisabled);
  1949.         return 0;
  1950.     }
  1951.     log (m->user, lognews, m->name);
  1952.     m->state = MBX_TUTOR;
  1953.     tutorserv (m->name, m, 2, m->usecolor, 0);
  1954.     return 0;
  1955. }
  1956. #endif
  1957.  
  1958.  
  1959.  
  1960. char *
  1961. wpage_exp (
  1962. char *to,
  1963. int hier OPTIONAL,
  1964. int exphome OPTIONAL        /* append and expand home bbs name ? */
  1965. ) {
  1966. #if (defined(ASKHOME) || defined(WPAGES))
  1967. char *cp = (char *) -1;
  1968. char *cp2;
  1969. char origbbs[40];
  1970. #ifdef WPAGES
  1971. char buf[12];
  1972. #endif
  1973.  
  1974.     if (strchr (to, '%'))
  1975.         return (to);
  1976. #ifdef ASKHOME
  1977.     /* This section adds the HOME BBS to any messages to known users that do
  1978.        not have "@bbs" portions of the TO address, except when user is a BBS    */
  1979.  
  1980.     cp2 = strchr (to, '@');
  1981.     cp = NULLCHAR;
  1982.     if ((cp2 == NULLCHAR) && (cp = findhome (to)) != (char *) NULL) {
  1983.         if (cp != (char *) -1) {    /* home no here */
  1984.             sprintf (origbbs, "%s@%s", to, cp);
  1985.             free (to);
  1986.             free (cp);
  1987.             to = strdup (origbbs);
  1988.         }
  1989.     }
  1990. #endif /* ASKHOME */
  1991. #ifdef WPAGES
  1992.     /* This section looks up the destination bbs in the White Pages file, if user not a BBS
  1993.        If found, the complete address is substituted    */
  1994.  
  1995. #ifdef ASKHOME
  1996.     if (cp != (char *) -1) {    /* if home not here */
  1997. #else
  1998.     if (cp == (char *) -1) {
  1999. #endif
  2000.         cp2 = strchr (to, '@');
  2001.         if (cp2 == NULLCHAR) {    /* no dest BBS given */
  2002.             if ((cp2 = wpageCheck (to, 0, 0, 'X')) != NULLCHAR) {    /* found the bbs */
  2003.                 free (to);
  2004.                 (void) strlwr (cp2);
  2005.                 to = cp2;
  2006.             }
  2007.             cp2 = strchr (to, '@');
  2008.         }
  2009.         if (hier && cp2 != NULLCHAR) {    /* we have a dest bbs, get correct, full haddress */
  2010.             cp = cp2++;
  2011.             if ((cp2 = wpageCheck (cp2, 1, 0, 'X')) != NULLCHAR) {
  2012.                 *cp = '\0';
  2013.                 sprintf (origbbs, "%s@%s", to, cp2);
  2014.                 free (to);
  2015.                 free (cp2);
  2016.                 (void) strlwr (origbbs);
  2017.                 to = strdup (origbbs);
  2018.             }
  2019.         }
  2020.     } else if (exphome) {
  2021.         (void) pax25 (buf, Mycall);
  2022.         if ((cp = strpbrk (buf, DIGI_IDS)) != NULLCHAR)
  2023.             *cp = '\0';    /* remove SSID */
  2024.         sprintf (origbbs, "%s@%s%s%s", to, buf,
  2025.              (Mbhaddress != NULLCHAR) ? "." : "",
  2026.              (Mbhaddress != NULLCHAR) ? Mbhaddress : "");
  2027.         free (to);
  2028.         to = strdup (origbbs);
  2029.     }
  2030. #endif /* WPAGES */
  2031. #endif /* ASKHOME || WPAGES */
  2032.     kwait (NULL);
  2033.     return (to);
  2034. }
  2035.  
  2036.  
  2037.  
  2038. #ifdef WPAGES
  2039. extern int MbWpages;
  2040.  
  2041. int
  2042. dombwpages (int argc, char *argv[], void *p)
  2043. {
  2044. struct mbx *m;
  2045. char buf[80], *cp, *cp2, origchar = 0;
  2046.  
  2047.     m = (struct mbx *) p;
  2048.  
  2049.     if (argc < 2) {
  2050.         tprintf (wp_syntax, m->privs & SYSOP_CMD ? " [@bbsname]" : "");
  2051.         return 0;
  2052.     }
  2053.     if (!(m->privs & SYSOP_CMD) && argc > 2) {
  2054.         tputs (sorry);
  2055.         return 0;
  2056.     }
  2057.     if (argc == 2) {    /* lookup */
  2058.         cp = wpageCheck (argv[1], 0, 0, 'X');
  2059.         if (!cp)
  2060.             tputs (notinwp);
  2061.         else {
  2062.             cp2 = wpage_exp (strdup (argv[1]), 1, 1);
  2063.             (void) strupr (cp2);
  2064.             tprintf (wplists2, cp2);
  2065.             free (cp2);
  2066.             free (cp);
  2067.         }
  2068.     } else {        /* else, setting it */
  2069.         if (argv[2][0] != '@')
  2070.             tputs (wp_sysopsyntax);
  2071.         else {
  2072.             if ((cp = strchr (argv[2], '.')) != NULLCHAR) {
  2073.                 sprintf (buf, &argv[2][1]);
  2074.                 (void) strupr (buf);
  2075.                 wpageAdd (buf, 1, 1, 'U');
  2076.                 origchar = *cp;
  2077.                 *cp = 0;
  2078.             }
  2079.             sprintf (buf, "%s%s", argv[1], argv[2]);
  2080.             (void) strlwr (buf);
  2081.             wpageAdd (buf, 0, 1, 'U');
  2082.             if (cp && origchar)
  2083.                 *cp = origchar;
  2084.             tputs (updating);
  2085.             tflush ();
  2086.             kwait (NULL);
  2087.             RenewWPages ();
  2088.         }
  2089.     }
  2090.     return 0;
  2091. }
  2092.  
  2093.  
  2094.  
  2095. static void
  2096. wpageUpdate (
  2097. FILE *fp,
  2098. char *string,
  2099. char *entry,
  2100. char *oldtime OPTIONAL,
  2101. int bbs,
  2102. int updateit,
  2103. char which
  2104. ) {
  2105. time_t now;
  2106. char buf[LINELEN], *cp;
  2107. char compare[40];
  2108. int thesize, changed = 0;
  2109. int thelen;
  2110. long offset;
  2111.  
  2112.     /* parameters string and oldtime are not being used, yet */
  2113.  
  2114.     thesize = (bbs) ? 32 : 13;
  2115.     (void) time (&now);
  2116.  
  2117.     /* make a comparison string from 'string' */
  2118.     strncpy (buf, string, (unsigned) thesize);
  2119.     buf[thesize] = 0;
  2120.     if ((cp = strchr (buf, ' ')) != NULLCHAR)
  2121.         *cp = 0;
  2122.  
  2123.     /* make a comparison string from 'entry' */
  2124.     strncpy (compare, entry, (unsigned) thesize);
  2125.     compare[thesize] = 0;
  2126.     if ((cp = strchr (compare, ' ')) != NULLCHAR)
  2127.         *cp = 0;
  2128.  
  2129.     if (!bbs && (cp = strchr (buf, '.')) != NULLCHAR)
  2130.         *cp = 0;
  2131.  
  2132.     /* has this entry changed ? */
  2133.     if (stricmp (compare, buf))
  2134.         changed = 1;
  2135.  
  2136.     /* if we are updating it, take the NEW entry */
  2137.     if (updateit && which != 'G')
  2138.         entry = buf;
  2139.  
  2140.     /* write the old or new entry, with the new timestamp and close file */
  2141.     fprintf (fp, "%-*s %-14ld\n", thesize, entry, now);
  2142.     (void) fclose (fp);
  2143.     kwait (NULL);
  2144.  
  2145.     /* If we were updating the entry and the entry DID change..... */
  2146.     if (changed && which != 'T') {
  2147.         if (updateit) {
  2148.             /* now we update the temporary wpages */
  2149.             if (!bbs) {    /* no temp for wpagebbs */
  2150.                 char buf2[LINELEN];
  2151.  
  2152.                 if ((cp = strchr (buf, '@')) != NULLCHAR)
  2153.                     thelen = (int) (cp - buf);
  2154.                 else
  2155.                     thelen = (int) strlen (buf);
  2156.                 if ((fp = fopentmp (WhitePages, READ_TEXT)) != NULLFILE) {
  2157.                     while (offset = ftell (fp), fgets (buf2, LINELEN - 1, fp)) {
  2158.                         if (!strnicmp (buf2, string, (unsigned) thelen)) {
  2159.                             fseek (fp, offset, SEEK_SET);
  2160.                             break;
  2161.                         }
  2162.                     }
  2163.                 } else
  2164.                     fp = fopentmp (WhitePages, APPEND_TEXT);
  2165.                 fprintf (fp, "%-*s %-14ld\n", thesize, buf, now);
  2166.                 (void) fclose (fp);
  2167.                 kwait (NULL);
  2168.             }
  2169.             /* record it in the daily WP Update temp file */
  2170.             if (bbs)
  2171.                 add_WPUpdate (buf, buf, NULLCHAR, which);
  2172.             else {
  2173.                 cp = strchr (buf, '@');
  2174.                 if (cp)
  2175.                     *cp++ = 0;
  2176.                 add_WPUpdate (buf, cp, NULLCHAR, which);
  2177.             }
  2178.         }
  2179.     }
  2180. }
  2181.  
  2182.  
  2183.  
  2184. /* Returns a copy (strdup'ed) of existing entry if string is in whitepages file */
  2185. char *
  2186. wpageCheck (char *string, int bbs, int updateit, char which)
  2187. {
  2188. /* note: updateit is NEVER set except sometimes when called from wpageAdd() */
  2189. register FILE *fp;
  2190. char buf[LINELEN], *retval = NULLCHAR;
  2191. register char *cp;
  2192. int result, thelen;
  2193. int entrysize;
  2194. char const *fname;
  2195. int skipupdate = 0;
  2196.  
  2197.     if (!MbWpages || string == NULLCHAR || !*string)
  2198.         return (retval);
  2199.     if (!strnicmp (string, "sysop", 5))
  2200.         return (retval);
  2201.     entrysize = (bbs) ? WPAGEBBSENTRYSIZE : WPAGEENTRYSIZE;
  2202.     fname = (bbs) ? WhitePagesBBS : WhitePages;
  2203.     if ((cp = strchr (string, (bbs) ? '.' : '@')) != NULLCHAR)
  2204.         thelen = (int) (cp - string);
  2205.     else
  2206.         thelen = (int) strlen (string);
  2207.     result = searchfile (string, fname, buf, entrysize, 0, thelen);
  2208.     if (result == -1 && !updateit) {
  2209.         if ((fp = fopennew (fname, READ_TEXT)) != NULLFILE) {
  2210.             while (fgets (buf, LINELEN - 1, fp)) {
  2211.                 if (!strnicmp (buf, string, (unsigned) thelen)) {
  2212.                     result = 0;
  2213.                     skipupdate = 1;
  2214.                     break;
  2215.                 }
  2216.             }
  2217.             (void) fclose (fp);
  2218.         }
  2219.     }
  2220.     if (result != -1) {    /* found it */
  2221.         if (((cp = strpbrk (buf, " \t")) != NULLCHAR))
  2222.             *cp = '\0';
  2223.         rip (buf);
  2224.         retval = strdup (buf);
  2225.         if (!skipupdate) {
  2226.             fp = fopen (fname, UPDATE_TEXT);
  2227.             if (fp != NULLFILE)    {
  2228.                 fseek (fp, (long) (long) result * (long) entrysize, 0);
  2229.                 wpageUpdate (fp, string, buf, &buf[(bbs) ? 33 : 14], bbs, updateit, (which != 'G') ? which : 'X');
  2230.                 /* wpageUpdate does the (void) fclose(fp); */
  2231.             }
  2232.         }
  2233.     }
  2234.     return retval;
  2235. }
  2236.  
  2237.  
  2238.  
  2239. void
  2240. wpageAdd (char *entry, int bbs, int updateit, char which)
  2241. {
  2242. time_t now;
  2243. FILE *fp;
  2244. char *last, buf[14];
  2245.  
  2246.     if (!MbWpages || entry == NULLCHAR)
  2247.         return;
  2248.     if (!strnicmp (entry, "sysop", 5))
  2249.         return;
  2250.     last = wpageCheck (entry, bbs, updateit, which);
  2251.     if (!last) {
  2252.         (void) time (&now);
  2253.         if (!bbs) {
  2254.             strncpy (buf, entry, 13);
  2255.             buf[13] = 0;
  2256.             if ((last = strchr (buf, '.')) != NULLCHAR)
  2257.                 *last = 0;
  2258.             entry = buf;
  2259.         }
  2260.         if ((fp = fopennew ((bbs) ? WhitePagesBBS : WhitePages, APPEND_TEXT)) != NULLFILE) {
  2261.             fprintf (fp, "%-*s %-14ld\n", (bbs) ? 32 : 13, entry, now);    /* Save h_addr in whitepages file */
  2262.             kwait (NULL);
  2263.             (void) fclose (fp);
  2264.         }
  2265.         if (bbs)
  2266.             add_WPUpdate (entry, entry, NULLCHAR, which);
  2267.         else {
  2268.             last = strchr (entry, '@');
  2269.             if (last)
  2270.                 *last++ = 0;
  2271.             add_WPUpdate (entry, last, NULLCHAR, which);
  2272.         }
  2273.     } else
  2274.         free (last);
  2275. }
  2276. #endif
  2277.  
  2278.  
  2279.  
  2280. #ifdef MAILCMDS
  2281. /* Returns 1 if string is in history file or if 2 string appears to be a
  2282.  * message id generated by our system or 0 if not ours or in history file.
  2283.  */
  2284. int
  2285. msgidcheck (register char *string)
  2286. {
  2287. register char *cp;
  2288.  
  2289.  
  2290.     if (string == NULLCHAR)
  2291.         return 0;
  2292.     /* BID's that we have generated ourselves are not kept in the history
  2293.      * file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
  2294.      * our hostname, truncated so that the BID is no longer than 11
  2295.      * characters.
  2296.      */
  2297.     if ((cp = strchr (string, '_')) != NULLCHAR && *(cp + 1) != '\0' &&
  2298.         strnicmp (cp + 1, Hostname, strlen (cp + 1)) == 0
  2299.         && *((Hostname) + strlen (cp + 1)) == '.'
  2300.         && (int) strspn (string, "0123456789") == (int) (cp - string))
  2301.         return 2;
  2302.  
  2303.     return (bid_check (string));
  2304. }
  2305. #endif
  2306.  
  2307.  
  2308.  
  2309. int
  2310. dombfdesc (int argc OPTIONAL, char *argv[], void *p)
  2311. {
  2312. struct mbx *m;
  2313. char *file, *cp, *nm;
  2314. FILE *fp;
  2315. int k;
  2316. #ifdef DOS_GETFILEATTR
  2317. unsigned attr;
  2318. char name[14];
  2319. #endif
  2320.  
  2321.     m = (struct mbx *) p;
  2322.     if ((file = permtest (m->path, m->privs, argv[1], RETR_CMD, NULLCHAR, 0)) == NULLCHAR) {
  2323.         tputs (Noperm);
  2324.         return 0;
  2325.     }
  2326. #ifdef DOS_GETFILEATTR
  2327.     (void) _dos_getfileattr (file, &attr);
  2328. #endif
  2329.     nm = strrchr (file, '/');
  2330.     if (nm == NULLCHAR)
  2331.         return 0;
  2332.     *nm++ = 0;
  2333. #ifdef DOS_GETFILEATTR
  2334.     if (attr & FA_DIREC) {
  2335.         sprintf (name, "%s/", nm);
  2336.         nm = name;
  2337.     }
  2338. #endif
  2339.     cp = pathname (file, index_dat);
  2340.     if ((fp = fopen (cp, APPEND_TEXT)) == NULLFILE) {
  2341.         tputs ("Can't open description file!\n");
  2342.         return 0;
  2343.     }
  2344.     fprintf (fp, "%-12s", nm);
  2345.     free (file);
  2346.     free (cp);
  2347.     tputs (filedesc);
  2348.     for (k = 1; k < 38; k++)
  2349.         tputc (uchar('0' + (k % 10)));
  2350.     tputc ('\n');
  2351.     while (mbxrecvline (m) != -1) {
  2352.         if (!strnicmp (m->line, "/ex", 3)) {
  2353.             (void) fclose (fp);
  2354.             return (0);
  2355.         }
  2356.         fprintf (fp, " %-37.37s\n", skipwhite (m->line));
  2357.     }
  2358.     (void) fclose (fp);
  2359.     return (-2);        /* socket closed here! */
  2360. }
  2361.  
  2362.  
  2363.  
  2364. #ifdef FILECMDS
  2365. int
  2366. dodownload (int argc, char *argv[], void *p)
  2367. {
  2368. struct mbx *m;
  2369. FILE *fp;
  2370. char *file;
  2371.  
  2372.     m = (struct mbx *) p;
  2373.     if (m->stype == 'I')
  2374.         return (dowhat (argc, argv, p));
  2375.     if (m->stype == 'E')
  2376.         return (dozap (argc, argv, p));
  2377.  
  2378.     if ((file = permtest (m->path, m->privs, argv[1], RETR_CMD, NULLCHAR, 0)) == NULLCHAR) {
  2379.         tputs (Noperm);
  2380.         mail_error (downloaddenied, m->name, cmd_line (argc, argv, m->stype));
  2381.         return 0;
  2382.     }
  2383. #ifdef UNIX
  2384.     if (!ftpsecuritycheck (file, m->privs, R_OK)) {
  2385.         tputs (Noperm);
  2386.         mail_error (downloaddenied, m->name, cmd_line (argc, argv, m->stype));
  2387.         return 0;
  2388.     }
  2389. #endif
  2390.     m->state = MBX_DOWNLOAD;
  2391. #ifdef TIPMAIL
  2392. #ifdef XMODEM
  2393.     if (m->stype == 'X') {
  2394.         if (m->type == TIP) {    /* xmodem send tip only */
  2395.             m->state = MBX_XMODEM_TX;
  2396. #ifdef MBXTDISC
  2397.             /* disable the mbox inactivity timeout timer - WG7J */
  2398.             stop_timer (&m->tdisc);
  2399. #endif
  2400.             (void) doxmodem ('S', file, m);
  2401.             return 0;
  2402.         } else {
  2403.             tputs (xmodemtip);
  2404.             return 0;
  2405.         }
  2406.     }
  2407. #endif
  2408. #endif
  2409.     if ((fp = fopen (file, (m->stype == 'U') ? READ_BINARY : READ_TEXT)) == NULLFILE)
  2410.         tprintf (cannotopen, file, SYS_ERRLIST(errno));
  2411.     else {
  2412. #ifdef MBXTDISC
  2413.         /* disable the mbox inactivity timeout timer - WG7J */
  2414.         stop_timer (&m->tdisc);
  2415. #endif
  2416.         if (m->stype == 'U')     /* uuencode ? */
  2417.             (void) uuencode (fp, m->user, file);
  2418.         else
  2419.             (void) sendfile (fp, m->user, ASCII_TYPE, 0);
  2420.         if (fp != NULLFILE)
  2421.             (void) fclose (fp);
  2422.     }
  2423.     free (file);
  2424.     return 0;
  2425. }
  2426. #endif
  2427.  
  2428.  
  2429.  
  2430. int
  2431. dombupload (int argc, char *argv[], void *p)
  2432. {
  2433. struct mbx *m;
  2434. FILE *fp, *uufp = NULLFILE;
  2435. char *file;
  2436. #ifdef UNIX
  2437. int mode = 0x7fff;
  2438. #endif
  2439.  
  2440.     m = (struct mbx *) p;
  2441.     if (m->stype == 'S') {
  2442.         m->stype = 'L';
  2443.         return (dombusers (argc, argv, p));
  2444.     }
  2445.     if (m->stype == 'F') {
  2446.         sprintf (m->line, "%s/%s", FingerDir, m->name);
  2447.         file = strdup (m->line);
  2448.     } else if (m->stype == '$') {
  2449.         sprintf (m->line, "%s/%s.sig", Signature, m->name);
  2450.         file = strdup (m->line);
  2451. #ifdef DELEGATE
  2452.     } else if (m->stype == 'M') {
  2453.         sprintf (m->line, "%s/%s.del", Signature, m->name);
  2454.         file = strdup (m->line);
  2455. #endif
  2456.     } else if ((file = permtest (m->path, m->privs, argv[1], STOR_CMD, NULLCHAR, 0)) == NULLCHAR) {
  2457.         tputs (Noperm);
  2458.         mail_error (uploaddenied, m->name, cmd_line (argc, argv, m->stype));
  2459.         return 0;
  2460.     }
  2461. #ifdef UNIX
  2462.     if (!ftpsecuritycheck (file, m->privs, W_OK)) {
  2463.         tputs (Noperm);
  2464.         mail_error (uploaddenied, m->name, cmd_line (argc, argv, m->stype));
  2465.         return 0;
  2466.     }
  2467. #endif
  2468.  
  2469. #if defined(FILECMDS) && defined(TIPMAIL) && defined(XMODEM)
  2470.     if (m->stype == 'X') {
  2471.         if (m->type == TIP) {    /* xmodem receive tip only */
  2472.             m->state = MBX_XMODEM_RX;
  2473. #ifdef MBXTDISC
  2474.             /* disable the mbox inactivity timeout timer - WG7J */
  2475.             stop_timer (&m->tdisc);
  2476. #endif
  2477.             (void) doxmodem ('R', file, m);
  2478.             goto secureit;
  2479.         } else {
  2480.             tputs (xmodemtip);
  2481.             return 0;
  2482.         }
  2483.     }
  2484. #endif
  2485.  
  2486.     if ((fp = fopen (file, (m->stype == 'U') ? WRITE_BINARY : WRITE_TEXT)) == NULLFILE) {
  2487.         tprintf (cannotcreate, file, SYS_ERRLIST(errno));
  2488.         free (file);
  2489.         return 0;
  2490.     }
  2491.  
  2492.     if (m->stype == 'U')    {
  2493.         uufp = fp;
  2494.         fp = tmpfile ();
  2495.     }
  2496.  
  2497.     log (m->user, logupload, file);
  2498.     m->state = MBX_UPLOAD;
  2499.     tprintf ("Send %s,  %s", (m->stype == 'F') ? "personal information" : (m->stype == 'S') ? "signature information" : (m->stype == 'M') ? "personal message" : "file", Howtoend);
  2500.     for ( ; ; ) {
  2501.         if (mbxrecvline (m) == -1) {
  2502.             unlink (file);
  2503.             break;
  2504.         }
  2505.         if (*m->line == 0x01 || !stricmp (m->line, "/abort")) {    /* CTRL-A */
  2506.             unlink (file);
  2507.             tputs (MsgAborted);
  2508.             break;
  2509.         }
  2510.         if (*m->line == CTLZ || !strnicmp ("/ex", m->line, 3) || !stricmp (m->line, "."))
  2511.             break;
  2512.         fputs (m->line, fp);
  2513. #if !defined(UNIX) && !defined(__TURBOC__) && !defined(TNOS_68K)
  2514.         /* Needed only if the OS uses a CR/LF
  2515.          * convention and putc doesn't do
  2516.          * an automatic translation
  2517.          */
  2518.         if (putc ('\r', fp) == EOF)
  2519.             break;
  2520. #endif
  2521.         if (putc ('\n', fp) == EOF)
  2522.             break;
  2523.     }
  2524.     if (m->stype == 'U')    {
  2525. #ifdef UNIX
  2526.         mode =
  2527. #else
  2528.         (void)
  2529. #endif
  2530.             uudecode (fp, uufp);
  2531.         (void) fclose (uufp);
  2532.     }
  2533.  
  2534.     (void) fclose (fp);
  2535.  
  2536. #if defined(FILECMDS) && defined(TIPMAIL) && defined(XMODEM)
  2537. secureit:
  2538. #endif
  2539.  
  2540. #ifdef UNIX
  2541.     if (CREATEsecure) {
  2542.         (void) chown (file, (uid_t) CREATEuid, (gid_t) CREATEgid);
  2543.         (void) chmod (file, (mode_t) (mode & CREATEmask));
  2544.     } else if (m->stype == 'U')
  2545.         (void) chmod (file, (mode_t) mode);    
  2546. #endif
  2547.     free (file);
  2548.     return 0;
  2549. }
  2550.  
  2551.  
  2552.  
  2553. void
  2554. bbsbump (
  2555. char *user,
  2556. int zap            /* if zap=1, remove entry, else just mark for bumping */
  2557. ) {
  2558. int i;
  2559. struct mbx *m = NULLMBX;
  2560.  
  2561.     /* check the mailbox users */
  2562.     for (i = 0; i < NUMMBX; i++) {
  2563.         if ((m = Mbox[i]) != NULLMBX) {
  2564.             if (!stricmp (m->name, user))
  2565.                 break;
  2566.         }
  2567.     }
  2568.     if (i != NUMMBX && m != NULLMBX) {
  2569.         if (zap)
  2570.             exitbbs (m);
  2571.         else
  2572.             m->privs |= EXCLUDED_CMD;
  2573.     }
  2574. }
  2575.  
  2576.  
  2577.  
  2578. int
  2579. dobump (int argc, char *argv[], void *p)
  2580. {
  2581. struct mbx *m;
  2582.  
  2583.     m = (struct mbx *) p;
  2584.     if (!(m->privs & SYSOP_CMD))
  2585.         tputs (sorry);
  2586.     else
  2587.         bbsbump (argv[1], ((argc > 2) && !strnicmp ("now", argv[2], 3)) ? 1 : 0);
  2588.     return 0;
  2589. }
  2590.  
  2591.  
  2592.  
  2593. int
  2594. dombencode (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
  2595. {
  2596. struct mbx *m;
  2597.  
  2598.     m = (struct mbx *) p;
  2599.     if (!(m->privs & SYSOP_CMD))
  2600.         tputs (sorry);
  2601.     else
  2602.         (void) doencode (0, (char **) 0, (void *) 0);
  2603.     return 0;
  2604. }
  2605.  
  2606.  
  2607.  
  2608. #ifdef FILECMDS
  2609.  
  2610. /* uuencode a file -- translated from C++; both versions copyright 1990
  2611.    by David R. Evans, G4AMJ/NQ0I
  2612. */
  2613.  
  2614. static int
  2615. uuencode (FILE *infile, int s, char *infilename)
  2616. {
  2617. int n_read_so_far = 0, n_written_so_far = 0, in_chars, n, mode = 0755;
  2618. unsigned long cnt = 0;
  2619. unsigned char in[3], out[4], line[100];
  2620. #ifdef UNIX
  2621. struct stat stb;
  2622.  
  2623.     if (stat (infilename, &stb) != -1)
  2624.         mode = stb.st_mode & 0777;    /* get real file protection mode */
  2625. #endif
  2626.     usprintf (s, "begin %03o %s\n", mode, infilename);
  2627.  
  2628.     /* do the encode */
  2629.     for ( ; ; ) {
  2630.         in_chars = (int) fread (in, 1, 3, infile);
  2631.         out[0] = in[0] >> 2;
  2632.         out[1] = uchar (in[0] << 6);
  2633.         out[1] = out[1] >> 2;
  2634.         out[1] = out[1] | (in[1] >> 4);
  2635.         out[2] = uchar (in[1] << 4);
  2636.         out[2] = out[2] >> 2;
  2637.         out[2] = out[2] | (in[2] >> 6);
  2638.         out[3] = uchar (in[2] << 2);
  2639.         out[3] = out[3] >> 2;
  2640.         for (n = 0; n < 4; n++)
  2641.             out[n] += ' ';
  2642.         n_read_so_far += in_chars;
  2643.         for (n = 0; n < 4; n++)
  2644.             line[n_written_so_far++] = out[n];
  2645.         if (((in_chars != 3) || (n_written_so_far == 60)) && n_read_so_far > 0) {
  2646.             line[(n_read_so_far + 2) / 3 * 4] = '\0';
  2647.  
  2648.             usprintf (s, "%c%s\n", n_read_so_far + ' ', line);
  2649.             kwait (NULL);
  2650.             cnt += (unsigned long) n_read_so_far;
  2651.             n_read_so_far = 0;
  2652.             n_written_so_far = 0;
  2653.         }
  2654.         if (in_chars == 0)
  2655.             break;
  2656.     }
  2657.     if (usprintf (s, " \nend\nsize %lu\n", cnt) == EOF)
  2658.         return 1;
  2659.     return 0;
  2660. }
  2661.  
  2662.  
  2663. int
  2664. uudecode (FILE *infile, FILE *outfile)
  2665. {
  2666. char line[100];
  2667. int header = 0;
  2668. int n_to_write, n_to_read, n_reads, n, m;
  2669. unsigned char b[4], out[3];
  2670. int mode = 0x7fff;
  2671.  
  2672.     rewind (infile);
  2673.     
  2674.     /* skip till the (begin) line is eaten */
  2675.     while (!header)    {
  2676.         (void) fgets(line, 100, infile);
  2677.         if (strstr (line, "begin"))    {
  2678.             header = 1;
  2679.             sscanf (line, "begin %03o", &mode);
  2680.         }
  2681.     }            
  2682.  
  2683.     /* decode the remainder of the file */
  2684.     while ((void) fgets (line, 100, infile), strncmp (line, "end", 3))    {
  2685.         n_to_write = (int)line[0] - 32;
  2686.         n_to_read = ((n_to_write + 2) / 3) * 4;
  2687.         if (strlen ((char *)line) - 2 < (unsigned int) n_to_read)    /* EOF apparently */
  2688.             n_to_read = 0;
  2689.         n_reads = n_to_read / 4;
  2690.         for (n = 0; n < n_reads; n++)    {
  2691.             for (m = 0; m < 4; m++)
  2692.                 b[m] = (unsigned char) line[1 + 4 * n + m] - 32;
  2693.  
  2694.             /* now do the actual decode */
  2695.             out[0] = (unsigned char) (b[0] << 2) | ((b[1] & 0x30) >> 4);
  2696.             out[1] = ((b[1] & 0x0f) << 4) | ((b[2] & 0x3c) >> 2);
  2697.             out[2] = ((b[2] & 0x03) << 6) | (b[3]);
  2698.             if (n_to_write > 3)
  2699.                 for (m = 0; m < 3; m++)
  2700.                     fputc(out[m], outfile);
  2701.             else
  2702.                 for (m = 0; m < n_to_write; m++)
  2703.                     fputc (out[m], outfile);
  2704.             n_to_write -= m;
  2705.         }
  2706.     }
  2707.     return (mode);
  2708. }
  2709.  
  2710.  
  2711. #endif
  2712. #endif /* MAILBOX */
  2713.